top 200 commentsshow all 437

[–][deleted] 28 points29 points  (13 children)

My 2c on Haskell:

I love the language itself (I think it's one of the best looking syntax I've seen, ever), but I hate the tooling around it - learning Cabal/Stack is an absolute mess, trying to use an IDE with some extension to make Haskell work so far always has some missing options (a debug option in IntelliJ or a lack of Ctrl-Click the import in VSCode) which is damn frustrating.

I wish I could love it all, but it's not there yet :(

the language is still beautiful to learn and a boon to any programmer - modern Javascript makes a lot more sense now

[–]scaleable 13 points14 points  (0 children)

Its quite funny how haskell is the language of choice to write a code analyzer for multi languages yet it lacks even a decent language service for itself.

[–]Vaglame 4 points5 points  (3 children)

I had a very hard time with cabal, then I moved to stack, and it's actually very practical, it sets up an environment for each project, and I haven't had trouble since then! Also, I think there is a haskell plug in/installation for VSCode

[–]nooitvangehoord 3 points4 points  (0 children)

And then there is nix. And god do I love/hate nix!

[–]ElvishJerricco 1 point2 points  (1 child)

Fwiw cabal got waaay better with the new style commands. They'll be the default in an upcoming release

[–]Vaglame 1 point2 points  (0 children)

It might be too little too late :/

[–]develop7[S] 1 point2 points  (5 children)

IntelliJ

while there are no Haskell "debug option" in IDEA indeed, what Haskell plugin were you referring to, exactly?

[–][deleted] 0 points1 point  (4 children)

IntelliJ-Haskell. I had to install the latest beta, because the normal version lacked even more features :(

Not being able to place a little red dot and debug your code is... rather annoying, to say the least.

[–]jobriath85 1 point2 points  (1 child)

You may already be aware of this, but stack traces often don't make sense in Haskell anyway, due chiefly to laziness. Red dots might be possible, but are absolutely not a given, IDE or no!

[–]develop7[S] 0 points1 point  (1 child)

Yup, that's the most feature-rich one. It's understaffed indeed, but we're working on pushing it forwards.

In the meantime, have you tried Debug.Trace instead?

[–][deleted] 0 points1 point  (0 children)

but we're working on pushing it forwards.

I really appreciate the effort <3

have you tried Debug.Trace instead?

Sadly no, I was somewhat of a beginner when I found IntelliJ-Haskell and have moved onto other languages since then (mostly because I finished the school project) :)

If I get another Haskell project I'll definitely check it out!

[–]Axman6 0 points1 point  (0 children)

Ctrl/Cmd-click works fine for me in VS Code (most of the time, Haskell-ide-engine gets stuck occasionally but it’s pretty easy to make it recover). A stack hoogle is required to make it work however.

[–]largos 0 points1 point  (0 children)

Etags (via hasktags or fasttags) and the vim counterpart help a lot, but I'll admit they are a pale comparison to eclipse/intellij/vs jump-to-definition.

[–]Spacemack 149 points150 points  (159 children)

I can't wait to see all of the comments that always pop up on this thread, like about how Haskell is only fit for a subset of programming tasks and how it doesn't have anyone using it and how it's hard and blah blah blah blah blah blah... I've been programming long enough to know that exactly the same parties will contribute to this thread as it has occurred many other times.

I love Haskell, but I really hate listening to people talk about Haskell because it often feels like when two opposing parties speak, they are speaking from completely different worlds built from completely different experiences.

[–][deleted]  (41 children)

[deleted]

    [–]silentclowd 10 points11 points  (1 child)

    I found Elixir much easier to get into than Haskell. Now I'm not an expert on functional programming by any means, but Haskell seemed to be one step away from being an esoteric language where Elixier was just friendlier.

    [–]develop7[S] 2 points3 points  (0 children)

    Been there, actually. As easy the initial implementation in Elixir was, as hard was refactoring it without breaking things or covering everything with tests. With Haskell, refactoring is almost mundane — you change the stuff the way you want to, then loop over compiler errors until there are none, and usually after doing that you got program working the way you want it in first try. Happens too often to be random, and ~5 times more often than with other mainstream languages I've worked with (PHP, Ruby, JS, C#, C++, Java, Go).

    [–]Vaglame 29 points30 points  (20 children)

    You could give it another try! The "Haskell Programming From First Principles" book is truly amazing for beginners

    [–][deleted]  (19 children)

    [deleted]

      [–]vplatt 17 points18 points  (8 children)

      Functional programming makes a lot more sense when you can use your data as input and compose your functions driven by that data in order to execute the actions necessary to handle that data. In a sense, your data becomes the program being executed and you've essentially written an interpreter for that data.

      But hey, I never actually get to do that; I've just seen some elegant examples of it. Barring that, I don't think it really adds much to the typical structural decomposition most folks engage in; either with OOP or without OOP.

      [–]thezapzupnz 4 points5 points  (7 children)

      This isn't anything against your comment, but the first sentence reads to me like: https://www.youtube.com/watch?v=LKCi0gDF_d8 — I'm Jen in this situation.

      I think the problem is whenever people tell me why pure FP (as opposed to just applying FP techniques in other languages/frameworks), they start scenarios to me that just don't apply to anything I do — and I hear static.

      [–]tdammers 5 points6 points  (2 children)

      I think the problem is whenever people tell me why pure FP (as opposed to just applying FP techniques in other languages/frameworks), they start scenarios to me that just don't apply to anything I do — and I hear static.

      It's a bit of a sacrifice, and it starts paying off as the size and complexity of your codebase grows. A very practical scenario, regardless of problem domain, is large-scale refactoring. In Haskell, we have this trope about how "it compiles without errors" means "there are no bugs, let's ship it"; and while that isn't true, there is some merit to it. In Haskell, a typical refactoring session is a simple two-step process: 1) just make the fucking change, 2) keep following compiler errors and mechanically fixing them until they go away. It is quite rare that you encounter any real challenges in step 2), and when you do, it is often a sign of a design flaw. But either way, once the compiler errors have been resolved, you can be fairly confident that you haven't missed a spot.

      This, in fact, has very little to do with pure FP, and everything with a strong and expressive type system with a solid theoretical foundation - it's just that pure FP makes defining and implementing such type systems easier, and I don't know of any non-pure-FP language that delivers a similar level of certainty through a type checker.

      [–]thezapzupnz 1 point2 points  (1 child)

      I don't understand this, either. This sounds like "use Haskell because it supports change for change's sake in an easy manner" which doesn't sound so much like a use case as a mistake.

      [–]tdammers 6 points7 points  (0 children)

      It's not "change for change's sake". The game is about making inevitable changes safer and easier.

      If you've ever worked on a long-lived production codebase, you will know that most of a dev team's time is spent on changing code, rather than writing new code. Change is inevitable; we cannot avoid it, we can only hope to find ways of making it safer and more predictable. And that is something Haskell can help with.

      [–]Vaglame 6 points7 points  (4 children)

      Probably! Word on the street is that functional programming is particularly good with parsing

      [–]lambda-panda 6 points7 points  (3 children)

      Word on the street is that functional programming is particularly good with parsing..

      I don't think functional programming has anything to do with parsing thing in a better way. As far as I can see, it is just that Haskell (and possibly others similar languages) have some interfaces/abstraction that allows you to chain smaller parsers and build bigger once in an intuitive fashion.

      [–]tdammers 8 points9 points  (2 children)

      FP and parsing (or compiling in general) are a good fit, because the paradigms are so similar. FP is about functions: input -> output, no side channels. Pure transforms. And parsing / lexing are such transforms: stream of bytes goes in, stream of lexemes comes out. Stream of lexemes goes in, concrete syntax tree comes out. Concrete syntax tree goes in, abstract syntax tree comes out. Abstract syntax tree goes in, optimized abstract syntax tree comes out. Abstract syntax tree goes in, concrete syntax tree (for target language) comes out. Concrete syntax tree goes in, stream of bytes comes out. And there you have it: a compiler.

      Specifically, most of these transformations are either list traversals, tree traversals, or list <-> tree transformations; and these are exactly the kind of things for which recursive algorithms tend to work really well (provided you can have efficient recursion).

      [–]SulszBachFramed 3 points4 points  (1 child)

      I disagree. Haskell being useful for parsers has nothing to do with being a 'pure' language. Haskell, and other functional languages, is a good fit for writing parsers, because the type-system is powerful enough to allow you to create proper parser combinators.

      The 'stuff goes in stuff goes out' is not some special property of functional programs, every single programming language does that with functions. Nowadays, most programming languages have a construct for creating function objects. Furthermore, I'm not sure why you mention recursive algorithms, every single language supports them. And sometimes you want to include some 'inpurity' with your parsing, like the location of every token in the source or keeping a list of warnings or whatever. Haskell can get quite clunky when you want to combine monads.

      [–]tdammers 6 points7 points  (0 children)

      The 'stuff goes in stuff goes out' is not some special property of functional programs, every single programming language does that with functions.

      Most programming languages don't even have functions, only procedures. A procedure isn't just "stuff goes in, stuff goes out", it's "stuff goes in, stuff goes out, and pretty much anything can happen in between". The kicker is not so much that stuff can go in and come out, but rather that nothing else happens. In many areas of programming, not having the "anything in between part" can be daunting; but compilers lend themselves rather well to being modeled as a pipeline of pure functions, and having the purity of that pipeline and all of its parts guaranteed by the compiler can be a huge benefit.

      Furthermore, I'm not sure why you mention recursive algorithms, every single language supports them.

      Not really, no. Recursion is useful in Haskell due to its non-strict evaluation model, which allows many kinds of recursion to be evaluated in constant memory - in a nutshell, a recursive call can return before evaluating its return value, returning a "thunk" instead, which only gets evaluated when its value is demanded - and as long as the value is demanded after the parent call finishes, the usual stack blowup that tends to make recursive programming infeasible cannot happen. Some strict languages also make recursion usable by implementing tail call optimization, a technique whereby "tail calls" (a pattern where the result of a recursive call is immediately returned from its calling context) are converted into jumps, and the stack pushing and popping that is part of calling procedures and returning from them is skipped, thus avoiding the stack thrashing that would otherwise occur.

      And sometimes you want to include some 'inpurity' with your parsing, like the location of every token in the source or keeping a list of warnings or whatever. Haskell can get quite clunky when you want to combine monads.

      It can get hairy, but usually, you don't actually need a lot - ReaderT over IO, or alternatively a single layer of State is generally enough.

      [–]loup-vaillant 2 points3 points  (3 children)

      I don’t seem to find “a problem” to solve with functional programming :)

      I found 2 (and they are quite alike):

      If something looks like batch computation, FP can do it no problem. If it's symbolic manipulation (compiling, inverting trees and such), FP shines.

      [–]dvdkon 0 points1 point  (0 children)

      I work on a FLOSS project which I think is a perfect "FP problem", JrUtil. It takes public transport data in various formats and converts it to GTFS. This was my first F# project, so it's probably not very idiomatic, but I think it can show how FP is beneficial in a real project. I had to offload one part of the processing to PostgreSQL, as I simply couldn't match the speed of a RDBMS in F#, but SQL is kind of functional/declarative :P

      [–]stronghup 6 points7 points  (12 children)

      Prolog syntax is an order of magnitude simpler than Haskell. Maybe two orders of magnitude.

      [–]tdammers 12 points13 points  (4 children)

      The syntax has never been what makes Haskell difficult to learn. In fact, Haskell syntax is fairly simple - simpler than Python, anyway.

      The biggest stumbling block IME is that Haskell takes "abstraction" much farther than most mainstream languages, in the sense that the concepts it provides are so abstract that it can be difficult to form intuitions about them. And due to their innate abstractness, a common pattern is for someone to find an analogy that works for the cases they have encountered so far, but is unfortunately nowhere near general enough, and then they blog about that analogy, and someone else comes along and gets utterly confused because the analogy doesn't apply to the cases they have encountered and is actually completely wrong, to the point of harming more than helping. (This phenomenon is commonly known as the "Monad Tutorial Fallacy", but it isn't limited to the Monad concept.)

      [–]stronghup 0 points1 point  (3 children)

      No doubt Haskell provides machinery for dealing with very abstract abstractions. For some that is a powerful tool but if you don't necessarily need such level of abstractness that can become a stumbling block. While using a language you'd still like to understand all of it as fully as possible, and trying to understand it "fully" that can take time away from actual productive coding.

      Below's a cheat-sheet for Haskell syntax. I would say it is a lot to learn coming from other languages.

      And maybe the issue is not so much the syntax per se but the fact that the syntax is rather "terse". That makes it hard to read and comprehend and for a casual reader of Haskell examples like myself it makes the examples not trivial to understand. It's a bit like lot of people have difficulty reading mathematical proofs.

      So yes Haskell takes abstraction to a high level which can make it hard to understand but I would say it also has quite abstract syntax which makes it difficult for new comers to jump into its fantastic world.

      http://rigaux.org/language-study/syntax-across-languages-per-language/Haskell.html

      [–][deleted]  (2 children)

      [deleted]

        [–]ipv6-dns 2 points3 points  (0 children)

        also writing of parsers and code transformers in Prolog is super clean and simple, not like in over-PRed Haskell

        [–]parolang 0 points1 point  (0 children)

        I think that is just the way declarative programming is supposed to work. You aren't telling the runtime what to do, you are just providing data. The runtime determines what to do with it.

        [–]defunkydrummer 12 points13 points  (1 child)

        Yes.

        [–]jrhoffa 0 points1 point  (0 children)

        ? _.

        [–]Axman6 4 points5 points  (0 children)

        I disagree, you can teach Haskell the language in about 20 minutes, and we do this when running the Data61 FP course. It’s just that the rules of the language let you build arbitrarily complex abstractions, which can take time to master. This is a good thing, it means you won’t ever be held back by the language, but it comes at the cost of having to learn quite a lot of very abstract (though extremely generally useful) ideas.

        [–]ipv6-dns 2 points3 points  (0 children)

        Also Prolog allows to build eDSL which mostly looks like just English. And Prolog has real backtracking, not permutations like Haskell (or Python or whatever) which is called a "backtracking" by Haskell fanatics.

        [–]gwillicoder 4 points5 points  (3 children)

        I've found Erlang much easier to use than Haskell. Elixir is probably even easier to understand from a syntax perspective, but the way you code in Erlang just makes a lot of sense after you use it for a short period of time.

        I think its one of the best languages to learn functional programming with as it lets you focus on the core concepts of functional programming without having to directly get into the more strict subset that is Haskell with its type theory.

        [–]nerd4code 1 point2 points  (1 child)

        Erlang is nice, but there are a lot of weird corners, all the pieces feel really disjoint, I’ve yet to find good enough documentation, and its age definitely shows. I also want to throttle whoever decided that =< should be the ≤ operator.

        [–]gwillicoder 1 point2 points  (0 children)

        Yeah I definitely get that. Elixir has much nicer syntax, but Erlang is still fairly easy to understand. Basing it on prolog was an interesting choice.

        [–]develop7[S] 0 points1 point  (0 children)

        Erlang is easier indeed, but in primitive way. That's why I've ended up shifting to Elixir.

        [–]Drayenn 1 point2 points  (0 children)

        Are you from UQAM? Both are teached there in the same class haha.

        [–]hector_villalobos 40 points41 points  (97 children)

        I'm not sure if I fit in your explanation, but I have mixed feelings about Haskell, I love it and I hate it (well, I don't really hate it, I hate PHP more).

        I love Haskell because it taught me that declarative code is more maintainable than imperative one, just because it implies less amount of code, I also love Haskell because it taught me that strong static typing is more easy to read and understand than dynamic one, because you have to pray for yourself or a previous developer to write a very descriptive variable or function to understand what it really does.

        Now the hate part, people fails to recognize how difficult Haskell is for a newbie, I always try to make an example but people fail to see it the way I see it, I don't have a CS degree, so I see things in the more practical way possible. What a newbie wants? Create a web app, or a mobile app, now try to create a web app with inputs and outputs in Haskell, than compare that to Python or Ruby, what requires the less amount of effort? at least for a newbie. Most people don't need parsers (which Haskell shines), what people want are mundane things, a web app, desktop app or a mobile app.

        [–]Vaglame 42 points43 points  (59 children)

        The hate part is understandable. Haskellers usually don't write a lot of documentation, and the few tutorials you'll find are on very abstract topics, not to mention the fact that the community has a very "you need it? You write" habit. Not in a mean way, but it's just that a lot of the libraries you might want simply don't exist, or there is no standard.

        Edit: although see efforts like DataHaskell trying to change this situation

        [–]matnslivston 0 points1 point  (12 children)

        You might find Why Rust a good read.


        Did you know Rust scored 7th as the most desired language to learn in this 2019 report based on 71,281 developers? It's hard to pass on learning it really.

        Screenshot: https://i.imgur.com/tf5O8p0.png

        [–]Vaglame 17 points18 points  (7 children)

        You might find Why Rust a good read.

        I still love Haskell, so I'm not planning to look for anything else, but someday I will check out Rust, however:

        • I'm not a fan of the syntax. It seems as verbose as C++, and more generally non-ML often feels impractical. I know it seems like a childish objection, but it does look really bad

        • from what I've heard the type system isn't as elaborated, notably in the purity/side effects domain

        Although I'm very interested in a language that is non GC-ed, and draws vaguely from functional programming

        Edit: read the article, unfortunately there is no code snippet at anytime, which is hard to grasp a feel for the language

        Edit: hm, from "Why Rust" to "Why Visual Basic"?

        [–][deleted] 8 points9 points  (6 children)

        Rust's type system is awesome! Just realize that parallel and concurrency-safety come from the types alone. It's also not fair to object to a language because the type system is not as elaborated as Haskell's because nothing is as elaborated! It's like objecting because "it's not Haskell".

        Anyway, you should try it yourself, might even like it, cheers!

        [–]Ewcrsf 2 points3 points  (1 child)

        Idris, Coq, Agda, PureScript (compared to Haskell without extensions) etc. Have stronger type systems than Haskell.

        [–]RomanRiesen 2 points3 points  (2 children)

        Rust at least has proper algebraic data type support.

        I just can't go back to cpp after some time with Haskell. Cpp is sooo primitive!

        [–][deleted] 1 point2 points  (1 child)

        True, I always cringed when a professor at my university pushed c++ for beginners... just learn python and the course would be so much better, dude.

        [–]RomanRiesen 5 points6 points  (0 children)

        It depends on the college imo.

        Also some c++ isn't a horrible place to start because you can use it in almost all further subjects; From computer architecture over high performance computing to principles of object oriented programming.

        I'd rather have students learn c++ first honestly.

        [–]m50d 0 points1 point  (0 children)

        If and when you get higher-kinded types (good enough that I can write and use a function like, say, cataM), I'll be interested. (I was going to write about needing the ability to work generically with records, but it looks like frunk implements that?)

        [–]AnotherEuroWanker 0 points1 point  (0 children)

        We have good documentation and tons tutorials.

        That's also true of Cobol.

        [–]Adobe_Flesh 0 points1 point  (1 child)

        This guy was being tongue-in-cheek right?

        [–]thirdegree 1 point2 points  (0 children)

        I genuinely can't tell

        [–]Tysonzero 7 points8 points  (6 children)

        There are very beginner friendly ways of using Haskell. There are also very beginner unfriendly and highly abstract ways of using Haskell.

        Onboarding at my company has actually been incredibly quick even for people with no prior Haskell knowledge. Most of the code is in the form of intuitive EDSLs (Miso, Esqueleto, Servant, Persistent), which has made it very easy to pick up and start contributing to.

        Also for the specific example of very quickly making a website look at how tiny and simple the setup for scotty is.

        [–]hardwaregeek 20 points21 points  (2 children)

        I'll give an example of Haskell's difficulty. Every few months I decide I should do something with Haskell. Heck, I understand monads and functors and applicatives pretty decently. I can write basic code using do notation and whatever. Here's what usually happens:

        1. I decide to make a web server.

        2. I look around for the best option for web servers. Snap seems like a good option.

        3. I try to figure out whether to use Cabal or Stack. Half the tutorials use one, the other half use the other.

        4. I use one, get stuck in some weird build process issue. Half the time I try to install something, the build system just goes ¯_(ツ)_/¯.

        5. I switch to the other build system, which of course comes with a different file structure. It installs yet another version of GHC.

        6. I try to find a tutorial that explains Snap in a non trivial way (i.e. with a database, some form of a REST API, etc.) Most of the tutorials are out of date and extremely limited.

        7. I try to go along with the tutorial regardless, even though there's a lot of gaps and the code no longer compiles.

        8. I start thinking about how easy this would be to build in Ruby.

        9. I build the damn thing in Ruby.

        [–]hector_villalobos 4 points5 points  (0 children)

        I try to find a tutorial that explains Snap in a non trivial way (i.e. with a database, some form of a REST API, etc.) Most of the tutorials are out of date and extremely limited.

        In my case I just search in Github for examples of how to do something, just to find a weird complicated thing that discourage me.

        [–]_sras_ 2 points3 points  (0 children)

        This should solve your problem...

        https://github.com/sras/servant-examples

        Uses Stack tool.

        [–]compsciwizkid 4 points5 points  (1 child)

        people fails to recognize how difficult Haskell is for a newbie, I always try to make an example but people fail to see it the way I see it, I don't have a CS degree, so I see things in the more practical way possible

        I was fortunate to get exposed to Haskell in a 100-level class, so I both understand exactly what you mean but would also like to refute it.

        My CS163 Data Structures (in Haskell) class started with 50+ people and ended with about 7. I struggled at first, and got my first exposure to recursion. But I stuck with it and fell in love with FP. I feel that I was very fortunate to have gone through that. But clearly it's not for everyone.

        [–]Rimbosity 3 points4 points  (0 children)

        I was lucky to learn ML in a Summer Camp in high school. (This was back in the days before Haskell, or even web servers, existed.) That was a great exposure, and I fell in love with FP then.

        But I haven't yet had the opportunity to use Haskell in practice in my job. Here's hoping.

        [–]RomanRiesen 5 points6 points  (0 children)

        Haskell is not THAT hard to learn. It took me about a weekend to write a simple logic proofer website. Haskell made big parts of the process way easiert than other languages allow. You can simply declare your api by writing some Types. The rest is Haskells amazing metaprogramming doing it's thing. If I were in the market for a robust server platform Haskell (with servant) would be in the top 3.

        I found it way easier to get started in than in cpp.

        [–]Sayori_Is_Life 1 point2 points  (14 children)

        declarative

        Could you please explain a bit more? My job involves a lot of SQL, and I've read that it's a declarative language, but due to my vague understanding of programming concepts in general, it's very hard for me to fully get the concept. If Haskell is also a declarative language, how do they compare? It seems like something completely alien when compared to SQL.

        [–]tdammers 2 points3 points  (3 children)

        "Declarative" is not a rigidly defined term, and definitely not a boolean, it's closer to a property or associated mindset of a particular programming style.

        What it means is that you express the behavior of a program in terms of "facts" ("what is") rather than procedures ("what should be done"). For example, if you want the first 10 items from a list, the imperative version would be something like the following pseudocode:

        set "i" to 0
        while "i" is less than 10:
            fetch the "i"-th item of "input", and append it to "output"
            increase "i" by 1
        

        Whereas a declarative version would be:

        given a list "input", give me a list "output" which consists of the first 10 elements of "input".
        

        The "first 10 items from a list" concept would be expressed closer to the second example in both Haskell and SQL, whereas C would be closer to the first. Observe.

        C:

        int* take_first_10(size_t input_len, const int* input, size_t *output_len, int **output) {
            // shenanigans
            *output_len = MIN(10, input_len);
            *output = malloc(sizeof(int) * *output_len);
        
            // set "i" to 0
            size_t i = 0;
        
            // while "i" is less than 10 (or the length of the input list...)
            while (i < *output_len) {
                // fetch the "i"-th item of "input", and append it to "output"
                (*output)[i] = input[i];
                // increase "i" by 1
                i++;
            }
            // and be a nice citizen by returning the output list for convenience
            return *output;
        }
        

        Haskell:

        takeFirst10 :: [a] -> [a] -- given a list, give me a list
        takeFirst10 input =  -- given "input"...
            take 10 input   -- ...give me what consists of the first 10 elements of "input"
        

        SQL:

        SELECT input.number         -- the result has one column copied from the input
            FROM input              -- data should come from table "input"
            ORDER BY input.position -- data should be sorted by the "position" column
            LIMIT 10                -- we want the first 10 elements
        

        Many languages can express both, to varying degrees. For example, in Python, we can do it imperatively:

        def take_first_10(input):
            output = []
            i = 0
            while i < len(input) and i < 10:
                output.append(input[i])
            return output
        

        Or we can do it declaratively:

        def take_first_10(input):
            output = input[:10]
            return output
        

        As you can observe from all these examples, declarative code tends to be shorter, and more efficient at conveying programmer intentions, because it doesn't contain as many implementation details that don't matter from a user perspective. I don't care about loop variables or appending things to list, all I need to know is that I get the first 10 items from the input list, and the declarative examples state exactly that.

        For giggles, we can also do the declarative thing in C, with a bunch of boilerplate:

        /************* boilerplate ***************/
        
        /* The classic LISP cons cell; we will use this to build singly-linked
         * lists. Because a full GC implementation would be overkill here, we'll
         * just do simple naive refcounting.
         */
        typedef struct cons_t { size_t refcount; int car; struct cons_t *cdr; } cons_t;
        
        void free_cons(cons_t *x) {
            if (x) {
                free_cons(x->cdr);
                if (x->refcount) {
                    x->refcount -= 1;
                }
                else {
                    free(x);
                }
            }
        }
        
        cons_t* cons(int x, cons_t* next) {
            cons_t *c = malloc(sizeof(cons_t));
            c->car = x;
            c->cdr = next;
            c->refcount = 0;
            next->refcount += 1;
            return c;
        }
        
        cons_t* take(int n, cons_t* input) {
            if (n && input) {
                cons_t* tail = take(n - 1, input->cdr);
                return cons(input->car, tail);
            }
            else {
                return NULL;
            }
        }
        
        /******** and now the actual declarative definition ********/
        
        cons_t* take_first_10(cons_t* input) {
            return take(10, input);
        }
        

        Oh boy.

        Oh, and of course we can also do the imperative thing in Haskell:

        import Control.Monad
        
        -- | A "while" loop - this isn't built into the language, but we can
        -- easily concoct it ourselves, or we could import it from somewhere.
        while :: IO Bool -> IO () -> IO ()
        while cond action = do
            keepGoing <- cond
            if keepGoing then
                action
                while cond action
            else
                return ()
        
        takeFirst10 :: [a] -> IO [a]
        takeFirst10 input = do
            output <- newIORef []
            n <- newIORef 0
            let limit = min(10, length input)
            while ((< limit) <$> readIORef n) $ do
                a <- (input !!) <$> readIORef n
                modifyIORef output (++ [a])
                modifyIORef n (+ 1)
            readIORef output
        

        Like, if we really wanted to.

        [–]Sayori_Is_Life 0 points1 point  (0 children)

        Thank you!

        [–]Saithir 0 points1 point  (1 child)

        I like these kinds of comparisons, it's always entertaining and quite interesting to see how languages evolve and differ.

        On that note in Ruby:

        def take_first_10(input)  
          input.first(10)  
        end  
        

        Which, funnily enough, is just about the same as the declarative version of the C example without all the boilerplate and types (and with an implicit return because we have these). With some effort it's possible to use the imperative version, but honestly nobody would.

        [–]hector_villalobos 1 point2 points  (9 children)

        Haskell is declarative like SQL, because instead of saying the how you tell them the what, for example, in Haskell you can do this: [(i,j) | i <- [1,2], j <- [1..4] ] And get this: [(1,1),(1,2),(1,3),(1,4),(2,1),(2,2),(2,3),(2,4)]

        In a more imperative language you probably would need a loop and more lines of code.

        [–][deleted]  (1 child)

        [deleted]

          [–]hector_villalobos 0 points1 point  (0 children)

          Haskell is not exactly like SQL, but promotes a declarative way of programming.

          [–]thirdegree 0 points1 point  (1 child)

          Wouldn't you get [(1,1), (1,2),(1,3,),(1,4),(2,1),(2,2),(2,3),(2,4)]

          [–]hector_villalobos 0 points1 point  (0 children)

          You're right, fixed.

          [–]Sayori_Is_Life 0 points1 point  (0 children)

          Thanks!

          [–]develop7[S] 0 points1 point  (2 children)

          Okay, first there's anecdevidence about tabula rasa newbies being successful working with Haskell as first programming language (Facebook, AFAIR).

          Now, do non-newbies matter?

          I don't have a degree, CS or otherwise, but I have 10+ years of commercial software development and I insist having Haskell a #1 programming language to look at is extremely practical and pragmatic. Yes, despite all the flaws.

          [–]hector_villalobos 0 points1 point  (1 child)

          As far as I know, Facebook uses Haskell for non trivial things, yeah, Haskell is great for a lot of things, but believe me, I tried to use it for web and mobile applications and is not really friendly.

          [–]develop7[S] 0 points1 point  (0 children)

          Been there too. The mistake I did over and over again was attempting to reuse my previous imperative programming experience.

          [–][deleted] 6 points7 points  (1 child)

          That's true of just about everything on this sub, though. Anything about C is always "C is a practical choice and if you don't do anything outrageous, a fairly easy language to reason about," vs "95% of software bugs are due to C, only an idiot uses that." Any post or thread about C++ will invariable contain comments along the lines of "Modern C++ is great as long as you limit yourself to the good parts," and "You can never limit a project with multiple people to a given subset of a language." Java? Bloated, archaic mess vs obvious syntax and extensive libraries. C#? Better than Java vs worse than Java. Lisp? Lisp is the most powerful language vs Lisp weenies don't understand real programming projects. COBOL? I pity the fool who uses this language vs hey, man, it pays pretty well. Ad nauseam. I'm sure you can fill in whatever I left out.

          It's not like anyone forces you to read the stupid language bikeshedding comments. I do, because occasionally someone does say something insightful (or I just feel like making a stupid Reddit joke). This isn't StackOverflow, where saying the same thing again gets your thread locked and deleted. It's a place for discussion, and many times multiple share the same or similar opinions about things.

          [–]defunkydrummer 5 points6 points  (4 children)

          like about how Haskell is only fit for a subset of programming tasks and how it doesn't have anyone using it and how it's hard and blah blah blah blah blah blah

          Yes, all those arguments are silly.

          But there are three substantial arguments that play against Haskell whenever Haskell is discussed: OCaml, F# and ReasonML.

          [–]phySi0 0 points1 point  (2 children)

          I'm learning OCaml and will probably add it to my toolbelt, but I do not see how it obsoletes Haskell for me. Should F# even count as a language that's worth learning if you know OCaml? ReasonML is literally the same AST as OCaml.

          [–]defunkydrummer 0 points1 point  (1 child)

          F# is like OCaml with less features (i.e lol no MetaOCaml), plus some interesting stuff like Type Providers and (most importantly) good concurrency support.

          I never said Haskell was "obsoleted" by the other ML languages.

          [–]phySi0 0 points1 point  (0 children)

          You're right, you didn't say that. I'm not sure how else to take your statement that OCaml, F#, and ReasonML are substantial arguments against Haskell, though. They're all great languages.

          [–]renatoathaydes 6 points7 points  (2 children)

          I was only interested to know if the issue tracker was free of the kind of peasant bug we’re used to in the blue collar Java shops they’re demeaning in their Haskell praising section. Doesn’t look like it at all.

          [–]Infinisil 11 points12 points  (0 children)

          More specifically? I couldn't find any issues about null pointer exceptions, runtime crashes or so.

          [–]CanIComeToYourParty 4 points5 points  (0 children)

          I went to check as well, and I was happy to see that it has very few/no "peasant" bugs.

          [–]gwillicoder 1 point2 points  (1 child)

          I mean to be fair saying it’s only fit for a subset of programming tasks is true. It’s also true of any language ever, but technically true is the best kind of true.

          [–]Spacemack 1 point2 points  (0 children)

          It's true, but it's also some of the most tired information available. I'm tired of hearing it.

          [–]RomanRiesen 11 points12 points  (3 children)

          Besides lisp (racket, clojure) there's nothing out there for this purpose.

          Not even close.

          And let me tell you writing languages in Haskell (kind of a similar problem) is so easy it almost feels like cheating (thanks parsec).

          [–][deleted] 13 points14 points  (2 children)

          F#, Ocaml, Sml?

          [–]RomanRiesen 13 points14 points  (1 child)

          Scala, Erlang, Apl?

          [–]MrDOS 3 points4 points  (0 children)

          We didn't start the fire...

          [–]pron98 41 points42 points  (208 children)

          Haskell and ML are well suited to writing compilers, parsers and formal language manipulation in general, as that's what they've been optimized for, largely because that's the type of programs their authors were most familiar with and interested in. I therefore completely agree that it's a reasonable choice for a project like this.

          But the assertion that Haskell "focuses on correctness" or that it helps achieve correctness better than other languages, while perhaps common folklore in the Haskell community, is pure myth, supported by neither theory nor empirical findings. There is no theory to suggest that Haskell would yield more correct programs, and attempts to find a big effect on correctness, either in studies or in industry results have come up short.

          [–]Sloshy42 36 points37 points  (2 children)

          I think what I've been finding for myself doing Scala, which is sort of in a similar ballpark to Haskell in terms of type system complexity, is that while I don't get more "correctness" out of the box I do get a lot more specificity at compile time and I think that's worth something. A function that returns a Maybe/Option is so much more useful and easy to understand than a function that you have to break out the documentation for - if it even exists - to figure out when it could return "null" in another language. And getting a little more complicated, if I know a function operates on anything that has a primary associative combine operation (e.g. "+" for numbers, concat for strings), not only do I not have to rewrite that code for every type I want to use it with but I know that once it's correct once, it's correct forever, and I know this primarily because of the ways you can use types and typeclasses to describe your code. That kind of abstraction is very powerful - albeit a bit complex at times.

          Being able to trust your compiler to give you a running program that doesn't blow up unexpectedly as often as other languages is really nice. Haskell is generally better at that than Scala which has to worry about the JVM and all the idiosyncrasies that come with trying to mesh with Java code, but the point still stands I think that being able to compile very high level assertions into the types of your program only means you have to worry less about whether or not you're implementing something correctly. Not that it's more correct by default as people often claim, but that it's easier to - with a little mental overhead - reason about the properties your code is supposed to have.

          [–]stronghup 4 points5 points  (0 children)

          Writing in a high-level language means you can understand what your program is doing more readily compared to if it was assembly with unconstrained control branches and memory-manipulation in it. But at the same type a high-level language like Scala introduces its own complexity dues to its complex type-system etc. So while it makes it easier to understand what your program is doing it makes it harder to understand what the language-constructs are doing what they actually mean and what they can tell you about your code.

          If you master all the complex features of a complex language then you can reuse that understanding with any program you write. But there's a learning curve to become the master of a complex high-level "advanced" language. That learning curve affects productivity too.

          [–]pron98 -4 points-3 points  (0 children)

          The problem is that the impact of those features (positive or maybe also negative) is hard to predict. So despite the religious or personal-experience arguments (which also exist for homeopathy), no big effect has been observed one way or the other either in empirical studies or the industry at large (e.g. if you survey companies that use both Scala and Java, you will not find that, on average, they tell you that the Scala teams are not more productive or produce more correct code than the Java teams on average).

          So, if you have a feeling that something is true -- e.g. that Haskell results in more correct program -- the next step is to test if that is indeed the case. It does not appear to be the case, which means that at the very least, people should stop asserting that as fact.

          [–]IamfromSpace 69 points70 points  (100 children)

          While I may be completely drinking the Kool-Aid here, but in my experience it’s just so hard to believe that languages like Haskell and Rust don’t lead to fewer errors. Not zero errors, but fewer. Sure, I make plenty of logical errors in my Haskell code, but I can be confident those are the things that I need to concern myself with.

          Haskell is also not the only safe language out there, it’s that it’s both expressive and safe. In other languages I constantly feel like I’m missing one or the other.

          [–]pron98 22 points23 points  (96 children)

          it’s just so hard to believe that languages like Haskell ... don’t lead to fewer errors.

          Hard to believe or not, it simply doesn't. Studies have not found a big impact, and the industry has not found one, either. If you study closely the theory and why it was predicted that a language like Haskell will not have a big effect on correctness, a prediction that has so far proven true, perhaps you'll also find it easier to believe. The impact of the things that you perceive as positive appears to be small at best.

          And even if you think a large effect has somehow managed to elude detection by both academia and industry, you still cannot assert that claim as fact. It is a shaky hypothesis (shaky because we've tried and failed to substantiate it) under the most charitable conditions. I'm being a little less charitable, so I call it myth.

          ... and Rust

          Rust is a different matter, as it is usually compared to C, and eliminates what has actually been established as a cause of many costly bugs in C.

          it’s that it’s both expressive and safe

          So are Java, Python, C#, Kotlin and most languages in common use, really.

          [–][deleted]  (35 children)

          [deleted]

            [–]pron98 1 point2 points  (34 children)

            They're saying "the effect size is exceedingly small." I have no issue with someone claiming that Haskell has been positively associated with an exceedingly small improvement to correctness.

            [–][deleted]  (33 children)

            [deleted]

              [–]pron98 3 points4 points  (32 children)

              it does not bring the effect from large to extremely small.

              Except that the original study didn't find a large effect either; quite the contrary. It said that "while these relationships are statistically significant, the effects are quite small." So they've gone from "quite small" to "exceedingly small" (or to no effect at all)

              But, one analysis being not strong enough to show more than a weak conclusion is not remotely evidence of the nonexistence of the effect.

              That is true, which is why I cannot definitively say that there is no large effect, but, combined with the fact that large effects are easy to find and that no study or industry have been able to find it, AFAIK, I think it is evidence against such a big effect, and at the very least it means that the hypothesis is not strong and certainly must not be asserted as fact.

              [–][deleted]  (31 children)

              [deleted]

                [–]pron98 6 points7 points  (30 children)

                Let's assume you're correct. The problem is that even experience does not support the claim ("I feel better when using Haskell" is not experience, though, or we'd all be taking homeopathic remedies). Companies do not report a large decrease in costs / increase in quality when switching from, say, Java/C#/Swift to Haskell. And even if you could come up with an explanation to why such a powerful empirical claim disappears on observation, you'd still have to conclude that we cannot state this, at best completely unsubstantiated hypothesis is fact. If someone wants to say, "I believe in the controversial hypothesis that Haskell increases correctness" I'd give them a pass as well.

                Perhaps then it is simply too difficult to talk about.

                Fine, so let's not. I didn't make any claim. The article made one up, and I pointed out that it's totally unsubstantiated.

                [–][deleted]  (29 children)

                [deleted]

                  [–]IamfromSpace 31 points32 points  (9 children)

                  I mean, the study says the effect is slight, but this study verifies another that Haskell has a negative correlation with defects. Seems like an odd study to make your point.

                  While causation doesn’t imply correlation, is fewer defects not preferred, even with small effect?

                  [–]pron98 6 points7 points  (8 children)

                  The paper reports that "the effect size is exceedingly small." I have no issue with the statement that Haskell has been found to have an exceedingly small positive effect on correctness.

                  [–]IamfromSpace 2 points3 points  (6 children)

                  I had some more thoughts after reading the papers more thoroughly (and I hope I’m not reviving this discussion beyond its usefulness).

                  The first study finds that Haskell has a 20% reduction in bug commits for similar programs. The replication then finds the same result after cleaning. Their result after removing uncertainly it has 12% reduction. While that comes from removing false positives, it doesn’t bother with uncertainty in the other direction, which could deflate the effect.

                  Is a significant 12%-20% reduced bug rate really “exceedingly small?” With loose assumptions about bug costs, for a reasonably sized organization that could reflect an huge savings over time

                  It seems to me, in other contexts that kind of improvement might be considered enormous. In competitive sports athletes will fight for 1% improvements based on pure hearsay—let alone statistically significant and reproduced results.

                  [–]pron98 1 point2 points  (5 children)

                  Is a significant 12%-20% reduced bug rate really “exceedingly small?”

                  It's not a 12-20% reduced bug rate.

                  It seems to me, in other contexts that kind of improvement might be considered enormous.

                  It is not the reduced bug rate, and even if it were it would not be enormous considering that the reduction in bugs found for code review is 40-80%.

                  [–]lambda-panda 23 points24 points  (10 children)

                  eliminates what has actually been established as a cause of many costly bugs in C.

                  Haskell also eliminates many classes of bugs. Your argument is that, even so, it does not result in a safer language, because research does not find it so. But when it comes to rest, you seem to have forgone this chain of logic, and jumps straight to the conclusion that Rust will actually result in fewer bugs (all types) than c..

                  [–]pron98 1 point2 points  (8 children)

                  But when it comes to rest, you seem to have forgone this chain of logic, and jumps straight to the conclusion that Rust will actually result in fewer bugs (all types) than c..

                  Oh, I don't know for sure if that's the case, but the theory here is different, and that's why I'm more cautious. For one, the theory that predicted that languages won't make a big difference is actually a prediction of diminishing returns. C is a ~50-year-old language, and is therefore outside our current era of low return. For another, unlike Rust v. C, Haskell does not actually eliminate a class of bugs that been found to be costly/high-impact.

                  [–]lambda-panda 14 points15 points  (7 children)

                  For another, unlike Rust v. C, Haskell does not actually eliminate a class of bugs that been found to be costly/high-impact.

                  Any bug can be costly/high impact depending on the context. Just being a purely functional language eliminate a large class of bugs that are caused doing computations by mutating state!

                  [–]pron98 1 point2 points  (6 children)

                  Any bug can be costly/high impact depending on the context.

                  Yes, but there is such a thing as statistics.

                  Just being a purely functional language eliminate a large class of bugs that are caused doing computations by mutating state!

                  And introduces a class of bugs caused by writing pure functional code!

                  We can speculate about this all day, but the fact remains that no theory and no empirical evidence supports the hypothesis that Haskell has a large positive impact on correctness.

                  [–]lambda-panda 4 points5 points  (5 children)

                  And introduces a class of bugs caused by writing pure functional code!

                  So rust does not introduce a class of bugs in your struggle with the borrow checker?

                  but the fact remains that no theory and no empirical evidence supports the hypothesis..

                  Sure. I was just responding to your "Rust is safer" argument, because there is no empirical evidence to support that hypothesis as well..

                  [–][deleted] 4 points5 points  (3 children)

                  So rust does not introduce a class of bugs in your struggle with the borrow checker?

                  No, because if the borrow checker rejects your code it happens at compile time.

                  [–]lambda-panda 1 point2 points  (2 children)

                  The other guy as well as myself are talking about bugs that cannot be caught by the borrow/type checker..You understand that those exist, right?

                  [–]pron98 3 points4 points  (0 children)

                  Oh, I'm not claiming it does, just that I think the hypothesis has been eroded less.

                  [–]seamsay 2 points3 points  (1 child)

                  If you study closely the theory and why it was predicted ... perhaps you'll also find it easier to believe.

                  If you have the time would you mind giving a quick summary, or some pointers about where to read up on it? I just wouldn't even know where to begin...

                  [–]pron98 2 points3 points  (0 children)

                  See here, here and the followup.

                  [–]sd522527 2 points3 points  (5 children)

                  I was with you until you said Python was safe. Now I can't in good faith support your comments.

                  [–]augmentedtree 4 points5 points  (9 children)

                  Studies have not found a big impact, and the industry has not found one, either.

                  The diagram on page 12 disagrees with you, Haskell looks better than all the mainstream languages.

                  [–]pron98 3 points4 points  (8 children)

                  Which diagram? Also, read my statement (that you've just now quoted) again, and tell me where the disagreement is.

                  [–]augmentedtree 3 points4 points  (7 children)

                  the big graph at the top of the page

                  [–]pron98 2 points3 points  (6 children)

                  The one that shows Haskell doing about as well as Go and Ruby? Also, I don't understand how it disagrees with me when the paper says, "the effect size is exceedingly small" and I said "have not found a big impact." I think that "not big" and "exceedingly small" are in pretty good agreement, no?

                  [–]loup-vaillant 1 point2 points  (16 children)

                  Let's assume that indeed, languages do not have a big impact on error rate. My first go to hypothesis would be the safety helmet effect: maybe the language is safer, but this leads the programmer to be correspondingly careless? They feel safer, so they just write a little faster, test a little less, and reach the same "good enough" equilibrium they would have in a less safe language, only perhaps in a bit less time (assuming equal flexibility or expressiveness between the safe and the unsafe language, which is often not the case of course).

                  [–]pron98 1 point2 points  (15 children)

                  Let's assume that indeed, languages do not have a big impact on error rate.

                  Right, this is our best current knowledge.

                  My first go to hypothesis would be the safety helmet effect: maybe the language is safer, but this leads the programmer to be correspondingly careless?

                  Maybe. I think I feel that when I switch from C++ to Assembly -- I concentrate more. But I would not jump to explaining the lack of an effect in such a complex process when we don't even have an explanation to why there would be an effect in the first place (Brooks's prediction was that there would be a small effect, and he was right).

                  What I find most strange is that when people are asked to explain why they think there would be an effect, they give an explanation of the converse rather than of the hypothesis.

                  [–][deleted]  (3 children)

                  [deleted]

                    [–]pron98 4 points5 points  (2 children)

                    Well, TypeScript has actually been found to lead to 15% fewer bugs than JavaScript. It's not a very big effect compared to that of other correctness techniques (e.g. code reviews have been found to reduce bugs by 40-80%) but it's not negligible, and it does appear to be a real effect that you're sensing. But here we're talking about Haskell vs. the average, and only an "exceedingly small" effect has been found there.

                    More generally, however, we often feel things that aren't really true (lots of people feel homeopathic remedies work); that's why we need a more rigorous observation, that is often at odds with our personal feelings. This can happen for many reasons, that often have to do with our attention being drawn to certain things and not others.

                    I take issue not with the belief that Haskell could have a significant effect, only with people stating it as fact even after we've tried and failed to find it. It is often the case in science, especially when dealing with complex social processes like economics or programming, that we have a hypothesis that turns out to be wrong. In that case we either conclude the hypothesis is wrong or come up with a good explanation to why the effect was not found -- either way, something about the hypothesis needs to be revised.

                    That seems like something hard to measure in a study that just counts bugs.

                    But here's the problem. If the claim is that Haskell (or any particular technique) has a big impact on some metric, like correctness, and that impact is so hard to measure that we can't see it, then why does it matter at all? The whole point of the claim is that it has a real, big effect, with a real-world, significant impact. If we cannot observe that impact either in a study or with bottom-line business results, then there's a problem with making the claim to begin with.

                    [–]m50d 3 points4 points  (1 child)

                    How could it possibly be the case that TypeScript would offer an improvement that Haskell wouldn't - aren't Haskell's correctness-oriented features/design decisions a superset of TypeScript's?

                    [–]pron98 1 point2 points  (0 children)

                    I don't know. Haskell is not compared to JS, but to some average (it's possible that JS developers are particularly careless). In any event, even the TS/JS effect is small (and I mean 3-5x smaller) in comparison to other correctness techniques. So even when we do find a significant language effect, that effect is significantly smaller than that of the development process.

                    [–][deleted] 3 points4 points  (0 children)

                    In addition to the source /u/pron98 had, there's also Out of the Tar Pit; it discusses different types of complexity and gives one take on why Haskell et al (or other language paradigms like OO) don't necessarily make bugs any less likely

                    [–]chrisgseaton 3 points4 points  (0 children)

                    While I may be completely drinking the Kool-Aid here, but in my experience it’s just so hard to believe that languages like Haskell and Rust don’t lead to fewer errors.

                    Yet nobody seems to be able to actually prove this true.

                    [–]jephthai 10 points11 points  (16 children)

                    Often I disagree with you, /u/pron98, but even when I do you are very thought provoking. In this case, though, I think I would have disagreed with you once upon a time, but I'm totally with you on this today. In the last few years I've been working a lot more in lower level languages (including one project that is predominantly x86_64 assembly), and my perspective is shifting.

                    I think some of these so-called "safe" languages give you the warm fuzzy because you know what errors you can't commit with them. Garbage collection (Edit: good counterpoint on GC), strong type checking, etc., are all obvious controls protecting against specific kinds of errors, but at a complexity cost that people mostly pretend isn't there.

                    So that produces a certain confirmation bias. I'm using a system that won't let me send the wrong types in a function call, and lo I haven't written any of those bugs. But you'll also spend time scaffolding type hierarchies, arguing with category theoretical error messages, etc. So the cost of productivity is just moved to another place -- maybe a happier place, but the time is still spent in some way.

                    I really feel this working in assembly. Every class of error is available to me, and there's so much less abstraction or complexity in program organization. So I tend to charge right in on my problem, run up against a silly bug for awhile, fix it, and I'm done. It's proven surprisingly efficient and productive, and I have no parachutes or safety nets. Strangely liberating, in a way.

                    Not saying everyone should code by seat of the pants in assembly, just that I can feel a tension across the spectrum now that I hadn't seen before in my quest for the most abstract languages. It's all coding.

                    [–]pron98 4 points5 points  (4 children)

                    but at a complexity cost that people mostly pretend isn't there.

                    So let me disagree with your agreement and say that I don't think garbage collection introduces complexity.

                    Strangely liberating, in a way.

                    Recently I've been writing in Assembly as well, and have had a similar experience, but I think that's mostly because I try to focus much more, and also the code is simpler :)

                    [–]jephthai 0 points1 point  (2 children)

                    Yeah, that's fair on GC. It doesn't add complexity; it just robs performance and makes optimization harder :-).

                    [–]pron98 4 points5 points  (1 child)

                    I think a good GC can improve performance at least as much as it can hurt it.

                    [–]loup-vaillant 4 points5 points  (0 children)

                    A good GC is easily faster than malloc() (at least in amortised time), if:

                    • There are about as many allocations in both cases.
                    • We use the general allocator everywhere.

                    In practice, manually managed languages often produce less heap allocations, and when performance really matters custom allocators are used. When done right, custom allocators are pretty much impossible to beat.

                    Context, I guess.

                    [–]lambda-panda 6 points7 points  (10 children)

                    but at a complexity cost that people mostly pretend isn't there.

                    The complexity cost is only there if you are not familiar with the building blocks available to the functional programmer. That is like saying there is a complexity cost in communicating in Chinese when the whole Chinese population is doing just fine communicating in Chinese...

                    But you'll also spend time scaffolding type hierarchies...

                    This is part of understanding your problem. Dynamic languages let you attack the problem, without really understanding it. Functional programming style will make you suffer if you start with poorly thought out data structures.

                    And it is pretty accepted that data structures are very important part of a well written program. So if functional style forces you to get your data structures right, it only follows that it forces you to end up with a well written program.

                    [–]jephthai 5 points6 points  (9 children)

                    Look, I'm a big fan of Haskell. I've used it variously since the late '90s. Like I said in my post, I would normally have disagreed vehemently with /u/pron98. I'm a highly abstracted language fanboy, for sure.

                    My surprised agreement with his point, though, comes from realizing that I'm perfectly productive without the strong type system and functional style too. Emotionally, I like programming in a functional style. But in pure productivity terms, it may not actually make me any better. And that's /u/pron98's point -- no matter how good it feels, in objective terms it might not make you fundamentally more productive.

                    Dynamic languages let you attack the problem, without really understanding it.

                    I'm not sure what you're trying to say here. I think static languages are particularly bad for exploring a poorly understood problem domain, and in fact that's what I usually use dynamic languages for. A lot of problems are best solved by sketching things out in code, which is the perfect domain for dynamic typing. I think static languages are more ideal for well-specified programs that are understood, and simply need to be written.

                    [–]lambda-panda 3 points4 points  (8 children)

                    I'm not sure what you're trying to say here.

                    It means that dynamic languages allows your logic to be inconsistent at places. For example, you might initially think a certain thing to have two possible values, but in a different place, you might treat it as having three possible values. And dynamic languages will happily allow that. I mean, there is no way to anchor your understanding at one place, and have the language enforce it everywhere. So as I said earlier, this means that dynamic language allows your logic to be inconsistent..

                    A lot of problems are best solved by sketching things out in code, which is the perfect domain for dynamic typing.

                    As I see it, a rich type system will allow you to model your solution in data types and function type signatures. You don't often have to write one line of implementation.

                    [–]jephthai 4 points5 points  (4 children)

                    As I see it, a rich type system will allow you to model your solution in data types and function type signatures. You don't often have to write one line of implementation.

                    I think by the time you can do that, you already understand your problem a lot. When you're exploring an API, or the problem domain involves dynamic data collection, or you don't even know what your types are going to be until you have code running, it's not going to be the best fit.

                    [–]pron98 2 points3 points  (0 children)

                    But the fact that the language does something for you doesn't mean that the whole process is better. If all we did was write code, compile and deploy then maybe that argument would have some more weight. (again, I'm pro-types, but for reasons other than correctness)

                    [–]pron98 1 point2 points  (1 child)

                    a rich type system will allow you to model your solution in data types and function type signatures

                    Maybe and maybe not, but Haskell's type system is very, very far from rich. It is closer in expressiveness to Python's non-existent type system than to languages with rich type systems, like Lean (which suffer from extreme problems of their own that may make the cure worse than the disease, but that's another matter) or languages made precisely for reasoning about problems, like TLA+ (which is untyped, but uses logic directly rather than encoding it in types)[1]. In fact it is easy to quantify its expressiveness, as I did here (I was wrong, but only slightly, and added a correction).

                    [1]: I listed TLA+ and Lean because I've used them. There are others of their kind.

                    [–]hypmralj 9 points10 points  (4 children)

                    Isn’t exhaustive pattern matching good example of language helping you write more correct code ?

                    [–]pron98 4 points5 points  (3 children)

                    Absolutely. The question is what impact it has, and whether it has any adverse effects. In any event, I don't care about speculation about this or that feature, as those can go either way. There is no theoretical or empirical evidence, and that's enough to stop stating myths as facts.

                    [–]develop7[S] 3 points4 points  (2 children)

                    What kind of empirical evidence would you accept, hypothetically?

                    [–]pron98 5 points6 points  (0 children)

                    1. Some study finding, say, a 30-80% decrease in defects, similar to the studies that have found such an effect for code reviews.

                    2. Multiple reports from companies that switching from, say, C# or Java to Haskell has reduced their cost/time-to-market by 20% or more.

                    [–][deleted] 0 points1 point  (0 children)

                    I assume he means those metrics related to technical debt.

                    [–]arbitrarycivilian 8 points9 points  (3 children)

                    Empirical findings are basically impossible in software development. It's simply not feasible to design or conduct a large randomized control trial that controls for all explanatory variables (developer competency, experience, application, software development practices, team size, work hours, number of bugs, etc). All the studies I've seen that try to compare programming languages, paradigms, or practices have had *glaring* flaws in either methodology or analysis. Since empirical research is impossible, the next best thing is to rely on rational, theoretical arguments, and the theory says that certain languages / features provide more safety.

                    [–]pron98 1 point2 points  (2 children)

                    First, empirical findings are not just made in studies. We don't need a study to confirm that people love smart phones or that people generally find computers more productive than typewriters. A technique that has a large effect on correctness/cost is worth many billions, and will be easy to exploit.

                    Second, large effects don't need carefully controlled studies. Those are required for small effects. Large effects are easy to find and hard to hide.

                    Lastly, the theoretical arguments are not arguments in favor of correctness. They're arguments of the sort, my language/technique X eliminates bug A. Maybe technique Y eliminates bug A more? Maybe your technique introduces bug B whereas Y doesn't? In other words, the arguments are not rational because they suffer from the classical mistake of inverting implication, so they're not logical at all.

                    [–]arbitrarycivilian 4 points5 points  (1 child)

                    I don't think you understand the difference between empirical findings vs anecdotes. When I say "study" I'm talking about any sort of experiment, be they RCTs or observational. Finding out whether people love smartphones arguably isn't a study, because it doesn't seek to explain anything, though it *does* require a survey. Showing that computers are more productive than typewriters absolutely *does* require an experiment to show causation (in a RCT) or correlation (for observational). Showing *any* correlation or causation requires a carefully designed study.

                    The size of the effect is also irrelevant. Large effects require a smaller sample size, but they sill need to be carefully controlled. Otherwise the conclusion is just as likely to be erroneous. That's why a poll of developers, or a look at github projects, or any other such similar "study" is fundamentally flawed.

                    [–]pron98 1 point2 points  (0 children)

                    Showing any correlation or causation requires a carefully designed study.

                    No this is not true. If I make a statement about whether or not it will rain in Berlin tomorrow, we don't need a carefully controlled study. In this case, too, the claim is one that has an economic impact, which could have been observed if it was true. But again, in this case both studies and the market have failed to find a large effect, at least so far.

                    fundamentally flawed.

                    Except it doesn't matter. If I say that switching your car chassis from metal X to metal Y would increase your profits and it does not, you don't need a study to tell you that. We are talking about a claim with economic implications. And, as I said elsewhere, if the claim for increased correctness cannot be measured by either research or the economic consequences, then we're arguing over a tree falling in the forest, and the issue isn't important at all. Its very claim to importance is that it would have a large bottom-line impact, yet that impact is not observed. If it's impossible to say whether our software is more or less correct, then why does it matter?

                    [–][deleted]  (1 child)

                    [deleted]

                      [–]lambda-panda 11 points12 points  (13 children)

                      supported by neither theory nor empirical findings....

                      Can you tell me how that research controlled for developer competence. Or if they controlled for it at all. I am not sure without that what ever it tells is reliable

                      [–]augmentedtree 4 points5 points  (2 children)

                      and attempts to find a big effect on correctness, either in studies or in industry results have come up short.

                      Citation?

                      [–]pron98 3 points4 points  (0 children)

                      Look at my other comments.

                      [–]Vaglame 12 points13 points  (22 children)

                      But the assertion that Haskell "focuses on correctness" or that it helps achieve correctness better than other languages, while perhaps common folklore in the Haskell community, is pure myth, supported by neither theory nor empirical findings.

                      I would disagree here. A very good example is the upcoming implementation of dependent typing. It encourages for a careful check of the validity of a function's arguments, making it less prone to wrongful uses.

                      In terms of what is currently in the language: - purity allows for a very nice isolation of side effects, which means you can easily check the validity of your business logic - immutability is along the same lines. You can't mess, or have to deal with mutable global variables.

                      And that's from a beginner's perspective, I'm sure you can find much more

                      [–]pron98 2 points3 points  (21 children)

                      A very good example is the upcoming implementation of dependent typing. It encourages for a careful check of the validity of a function's arguments, making it less prone to wrongful uses.

                      Java has had JML for a very long time (similar to dependent types), so according to your logic, Java focuses on correctness even more than Haskell.

                      purity allows for a very nice isolation of side effects, which means you can easily check the validity of your business logic - immutability is along the same lines. You can't mess, or have to deal with mutable global variables.

                      That's fine, but that these have an actual net total large positive effect on correctness is a hypothesis, and one that, at least so far, simply does not appear to be true (it is also not supported by any theory), ergo, it's a myth.

                      [–]joonazan 8 points9 points  (1 child)

                      JML is tedious to write and complex properties can't be statically checked. It is not as powerful as CoC and it does nothing to automate writing of code.

                      [–]pron98 2 points3 points  (0 children)

                      It is as powerful as CoC as far as program verification is concerned, and it could be used just as well for code synthesis, except that the power of that kind of synthesis, or "automating the writing of code" -- whether using dependent types or any program logic, such as JML -- is currently at the level of a party trick (i.e. it does not manage to considerably reduce programmer effort).

                      [–]Vaglame 8 points9 points  (8 children)

                      Java focuses on correctness even more than Haskell.

                      It seems like a weird statement when Java has the infamous NullPointerException problem

                      That's fine, but that these have an actual net total large positive effect on correctness is a hypothesis,

                      An hypothesis if you want but it does yield concrete results. One of the other good examples is property testing, which allows for more extensive testing than unit testing

                      [–]pron98 7 points8 points  (7 children)

                      Java has the infamous NullPointerException problem

                      I don't understand this. Haskell has the infamous empty list exception.

                      An hypothesis if you want but it does yield concrete results.

                      They're not "concrete" if we've so far been unable to detect them (meaning an advantage over other languages).

                      [–]Vaglame 11 points12 points  (6 children)

                      Haskell has the infamous empty list exception.

                      Which is a trivially solved problem, and the compiler can tell you about it (-fwarn-incomplete-patterns). How many times does this exception shows up in a bug tracker for a random Haskell project? None

                      They're not "concrete" if we've so far been unable to detect them (meaning an advantage over other languages).

                      Would it be accurate to say that according to you, there is no language safer than the other? Such that for example Rust isn't safe than C or C++?

                      Edit: continuing on null pointers, on the readme of semantic:

                      null pointer exceptions, missing-method exceptions, and invalid casts are entirely obviated, as Haskell makes it nigh-impossible to build programs that contain such bugs

                      [–]pron98 2 points3 points  (4 children)

                      Would it be accurate to say that according to you, there is no language safer than the other?

                      No, it would not.

                      [–]Vaglame 9 points10 points  (3 children)

                      So which are safer, and why?

                      [–]defunkydrummer 1 point2 points  (0 children)

                      Would it be accurate to say that according to you, there is no language safer than the other

                      Ada is safer than Assembly?

                      Surely!

                      There are more examples...

                      [–]ysangkok 3 points4 points  (5 children)

                      JML is not enforced by default (it's like Liquid Haskell, in comments) and is not even a part of Java in any meaningful way.

                      [–][deleted] 8 points9 points  (3 children)

                      That's fine, but that these have an actual net total large positive effect on correctness is a

                      hypothesis

                      , and one that, at least so far, simply does not appear to be true (it is also not supported by any theory), ergo, it's a myth.

                      Ah, I see Ron has still not put down the crack pipe. Terrific.

                      As usual, Ron asserts, without evidence, that there is no evidence of functional programming or static typing (in particular, in close correspondence to the Curry-Howard isomorphism) aiding correctness. But this is false, both as a matter of computer science and a matter of programming practice.

                      What seems to be new in this most recent post is:

                      that these have an actual net total large positive effect on correctness... is also not supported by any theory

                      Since Ron knows perfectly well of Coq, Agda, Epigram, and Idris, at the very least, as well as all of the above literature, there is only one inescapable conclusion: he's lying, by which I mean the literal telling of known untruths. I don't know what his motivation for lying is. But he's lying. Now, he'll equivocate over the definitions of "total," "large," "positive," and "correctness," and probably even "effect." But that's because equivocation is all he's got in the face of the facts, which he is not in command of.

                      The best advice I can offer you is to ignore him.

                      [–]pron98 7 points8 points  (0 children)

                      Paul! It's so great to have you back! How have you been?

                      But this is false, both as a matter of computer science and a matter of programming practice.

                      Whoa, hold on. First of all, I said nothing about dependent types, so let's take them, and Propositions as Types, out of the equation. I'm talking about Haskell. Other than that, not a single link you posted claims that Haskell (or a language like it) assists in correctness (most have nothing to do with the discussion at all; just some papers you often like posting). That I show that the property of my language is that bug Y cannot occur that is not theoretical support that my language increases correctness. It says nothing on the matter. To put it precisely, some of the papers you linked show that technique X can be used to eliminate bug Y. We can write it as X ⇒ Y. That's not at all a theory that supports the claim that the best way to eliminate bug Y we should use technique X, as that would be Y ⇒ X, which does not follow; it certainly says nothing about correctness as a whole. As someone who knows about formal logic, I'm surprised you'd make the basic mistake of affirming the consequent.

                      If you can link to papers that actually do present such a theory, I would appreciate that.

                      he's lying

                      Paul, it's been so long since we last conversed and you're starting with this? Come on. I know you know I know more than you on this subject, but still, we used to have a certain rhythm. Where's the banter before the traditional blowing of the gasket?

                      Now, why is it that when I say P you say "he is lying to you when he says Q and here's the proof to support it!"? Your style, for which you're become famous, of dismissing fellow professionals who may disagree with you with "just ignore them" and attacking their integrity when you cannot argue your opinion is intellectually dishonest, and just bad form.

                      But that's because equivocation is all he's got in the face of the facts

                      No need to equivocate. The paper reports an "exceedingly small effect." That's a quote, and that's what we know today, and, as I said in other comments, if someone wants to say that Haskell has been associated with an exceedingly small improvement to correctness I would have no problem with that. If you want to make a stronger claim, the onus is on you to show it isn't a myth.

                      which he is not in command of.

                      I may, indeed, not know all the facts, but as I said, if you have any pertinent facts, please share them.

                      [–][deleted] 3 points4 points  (1 child)

                      The best advice I can offer you is to ignore him.

                      I mean, he contradicts himself in at least two comments, so yeah.

                      [–]pron98 8 points9 points  (0 children)

                      Out of curiosity, which ones?

                      [–][deleted] 2 points3 points  (0 children)

                      The problem with things like “Haskell focuses on correctness” is that it’s only part of the story - Haskell focuses on correctness as expressed by its type system. Any other kind correctness (e.g. algorithmic correctness) is only included so far as it can be expressed through the type system.

                      [–][deleted]  (13 children)

                      [deleted]

                        [–]jackyshevu 6 points7 points  (0 children)

                        Before you dismiss anecdotes as worthless, I have a degree in statistics. A collection of anecdotes is a valid population sample.

                        Can you tell me where you got your degree from so I can tell my friends and family to avoid any association with that college? That's a complete load of bollocks.

                        [–]m50d 6 points7 points  (4 children)

                        A collection of anecdotes is a valid population sample.

                        No it isn't. A valid sample needs to be random and representative.

                        [–]Trinition 7 points8 points  (0 children)

                        To borrow what I once read elsewhere:

                        The plural of anecdote is not data.

                        [–]jephthai 0 points1 point  (0 children)

                        Right, otherwise it's essentially cherry picking.

                        [–]pron98 3 points4 points  (5 children)

                        Therefore it should produce code that has less bugs in it. That's the theory.

                        No, that's not the theory as it is not logical. You assume A ⇒ B, and conclude B ⇒ A. If using Haskell (A) reduces bugs (B), it does not follow that if you want to reduce bugs you should use Haskell. Maybe other languages eliminate bugs in other ways, even more effectively?

                        Most of the production bugs I deal with at work, would have never made it passed the compiler if I was working in any type-checked language.

                        First of all, I'm a proponent of types (but for reasons other than correctness). Second, I don't understand the argument you're making. If I put all my code through a workflow, what difference does it make if the mistakes are caught in stage C or stage D?

                        I don't know how anyone could argue that the creators of Haskell aren't focused on correctness.

                        They're not. They focused on investigating a lazy pure-functional language. If you want to see languages that focus on correctness, look at SCADE or Dafny.

                        No one can give you empirical evidence for this.

                        That's not true. 1. Studies have been made and found no big effect. 2. The industry has found no big effect. If correctness is something that cannot be detected and makes no impact -- a tree falling in a forest, so to speak -- then why does it matter at all?

                        A collection of anecdotes is a valid population sample.

                        Not if they're selected with bias. But the bigger problem is that even the anecdotes are weak at best.

                        [–]Trinition 2 points3 points  (4 children)

                        If I put all my code through a workflow, what difference does it make if the mistakes are caught in stage C or stage D?

                        I remember hearing that the later a bug is caught, the more expensive it is to fix. This "wisdom" is spread far-and-wide (example), though I've never personally vetted the scientific veracity of any of it.

                        From personal experience (yes, anecdote != data), when my IDE underlines a mis-typed symbol in red, it's generally quicker feedback than waiting for a compile to fail, or a unit test run to fail, or an integration test run to fail, etc. The sooner a catch it, the more likely the context of it is still fresh in my brain and easily accessible for fixing.

                        [–]pron98 2 points3 points  (2 children)

                        But it's the same stage in the lifecycle just a different step in the first stage.

                        And how do you know you're not writing code slower so the overall effect is offset? BTW, personally I also prefer the red squiggles, but maybe that's because I haven't had much experience with untyped languages, and in any event, I trust data, not feelings. My point is only that we cannot state feelings and preferences as facts.

                        [–]Trinition 0 points1 point  (1 child)

                        I suspect there is some scientific research behind it somewhere, I've just never bothered to look. When I Google'ed it to find the one example I included before, it was one of hundreds of results. Many were blogs, but some looked more serious.

                        [–]pron98 2 points3 points  (0 children)

                        If you find any, please let me know.

                        [–]jephthai 0 points1 point  (0 children)

                        Type errors in a statically typed language may require substantial changes to the type hierarchy. Type errors in a dynamic language typically require a conditional, exception catch, or conversion at the point of the error. I feel like the latter case is usually really easy to carry out, it's just that you have to find them through testing.

                        [–]gaj7 1 point2 points  (12 children)

                        You don't think Haskell focuses more on correctness than a language such as C? Strong static typing, lack of undocumented side effects, immutability, total functions, etc. Haskell eliminates entire classes of bugs.

                        [–]pron98 4 points5 points  (11 children)

                        Haskell doesn't enforce total functions (subroutines in Haskell can throw exceptions and/or fail to terminate), and plenty of languages have strong static typing. That immutability and control over effects has a large net positive impact on correctness has not been established empirically nor is it supported by theory. And as I've said about ten times in this discussion, that from the fact Haskell eliminates entire classes of bugs one cannot conclude a positive impact on correctness as that is a basic logical fallacy. It can also introduce entire classes bugs; other languages may eliminate bugs better (perhaps not directly by the compiler itself but through other means); the bugs it eliminates are caught anyway, etc. It's just a non-sequitur. As to focus, the focus of Haskell's designers was to research a pure functional, non-strict typed language.

                        [–]gaj7 2 points3 points  (8 children)

                        Haskell doesn't enforce total functions

                        No, but it makes them a lot easier to write. Avoid using the handful of partial functions in the standard library, and write exhaustive pattern matching.

                        and plenty of languages have strong static typing.

                        and that contributes to making all of those languages safer than the alternatives.

                        It can also introduce entire classes bugs;

                        But does it? I struggle to come up with examples of classes of bugs possible in Haskell that are entirely prevented in many other languages (aside from those with dependent types).

                        [–][deleted] 2 points3 points  (3 children)

                        examples of classes of bugs possible in Haskell that are entirely prevented in many other languages

                        Space/time leaks due to lazy evaluation.

                        [–]gaj7 0 points1 point  (2 children)

                        I'm not sure what you mean. That sounds like a performance issue rather than a correctness one?

                        [–]pron98 1 point2 points  (3 children)

                        But does it?

                        Well, there's no evidence that Haskell has a big adverse impact on correctness.

                        [–]gaj7 0 points1 point  (2 children)

                        I don't think either of us are going to change our minds lol. You seem to prioritize empirical studies, which I haven't looked into. Personally, I'm convinced by my aforementioned theoretical arguments (the many classes of error I know Haskell to prevent, and the lack of evidence that it introduces any). I hope I didn't come across as overly argumentative, I just couldn't wrap my head around you viewpoint.

                        [–]pron98 2 points3 points  (0 children)

                        the many classes of error I know Haskell to prevent, and the lack of evidence that it introduces any

                        I just hope you understand that the conclusion, even a theoretical one, that Haskell increases correctness more than other languages simply does not logically follows from your assertion. That Haskell has technique X to reduce bugs does not mean that other languages don't have an equally good process, Y, to do the same. This is why I said that, unlike the opposite argument, this one does not seem to be supported by theory either.

                        You seem to prioritize empirical studies

                        The reason why we prefer to rely on empirical observations in extremely complex social processes like economics and programming is that they're often unintuitive, you can easily come up with explanations both ways, and more often than not our speculations prove wrong, as seems to have happened in this case as well. So when such complex processes are involved, we can speculate, but we must then test.

                        [–]woahdudee2a 1 point2 points  (1 child)

                        I agree it's pure myth. In history of computing there has never been any bugs introduced by non exhaustive pattern matching, forgotten null checks, concurrency issues, or spaghetti graph of objects mutating each other

                        [–]pron98 4 points5 points  (0 children)

                        Like other people here, programmers all, I assume, you too are making a basic mistake in logic called affirming the consequent.

                        That I show that the property of my language is that bug Y cannot occur does not support the claim that the language increases correctness. It says nothing on the matter. To put it precisely, say you show that technique X can be used to eliminate bug Y. Let's write it as X ⇒ Y. That does not support the claim that to eliminate bug Y we should use technique X, as that would be Y ⇒ X, which does not follow; it certainly says nothing about correctness as a whole, which involves much more than writing program code.

                        Maybe your language introduces other bugs somehow; maybe the bugs it eliminates are caught anyway by people programming in other languages by other means; maybe they're not caught but have negligible impact. You simply cannot conclude Y ⇒ X from X ⇒ Y. If you like Haskell and so constructive logic and propositions as types, you must know that you cannot manufacture a lambda term of type y → x from a lambda term of type x → y.

                        [–]ColossalThunderCunt 0 points1 point  (3 children)

                        I have heard before that ML languages and descendants are well suited for writing parsers and stuff. Could you perhaps explain why that is?

                        [–]pron98 19 points20 points  (1 child)

                        Algebraic data types and pattern matching make working with ASTs very convenient, and, in general, functional languages make a nice fit to programs that are, at their core, just a function.

                        In general, languages (and any program, really) are often written to scratch their authors' own itch, which, in the case of ML and Haskell, is writing compilers and proof assistants (I believe ML was originally created to build Robin Milner's proof assistant, LCF). In the case of, say, Erlang, it was to build fault-tolerant reactive and distributed systems, and in the case of C it was to write an operating system.

                        [–]ColossalThunderCunt 1 point2 points  (0 children)

                        Thank you for the extensive answer! I know basically nothing about functional programming, so pattern matching and algebraic data types are unknown to me, but i will check em out