1. 19
  1.  

  2. 42

    I think this article is bad. It says things like

    Abstractions with types is a bad type of abstraction because it ignores the basic fact that programs deal with data, and data has no types.

    followed by some argument about how natural language supposedly has no types. That’s just not even wrong. In studies of (natural) languages you assign all kinds of ‘types’ to parts of languages, because that makes it a lot easier (!) to reason about the meanings/properties of communication.

    1. 11

      Yes! In particular you’ve reminded me of Montague semantics, a category-theoretic approach that blends parsing and type-checking. A Montague system not only knows how to put words together, but knows how the meanings of each component contribute to the meaning of the entire utterance.

      1. 4

        Funnily enough, there’s an even more direct link via recent research into type-theoretic modelling of natural language semantics. Whilst Montague grammar has a few coarse “types” for different grammatical constructs, this approach assigns more specific types to concepts and is a literal application of a dependent type theory. See for example this paper: https://www.stergioschatzikyriakidis.com/uploads/1/0/3/6/10363759/type-theory-natural.pdf

      2. 8

        Yeah, that part wasn’t particularly well thought out. It seemed to me like an undeveloped argument for dynamic vs static types. That’s a separate problem, but the author seems to simply favor dynamic languages. Dynamic languages are the only ones he complimented in the article at least.

        However, the surrounding argument, about the lack of maturity in the tooling and shortage of successful software projects built in Haskell is a fair argument. Yes, there’s pandoc and a few static analysis tools built in Haskell, but IMO that’s a bit of a cop out, since parsers/compilers are trivial to implement in a functional language. None of those projects say much about the effectiveness or benefit of using Haskell to solve more general software engineering problems.

        I also think the criticism of Haskell using its own terminology is valid. This cuts the Haskell community off from the rest of software developers without much gain (as viewed from the outside at least). It’s fine to note the ties between the various mathematical and language concepts, but expecting a new developer to learn the plethora of terms required to even read the stdlib docs is a tall order.

        Rust has some of the same features, but does a better job of introducing them with concrete examples rather than abstract type definitions. Abstract concepts are fine, but without any proven benefits its going to be hard to motivate people to learn and use them.

        1. 7

          However, the surrounding argument, about the lack of maturity in the tooling and shortage of successful software projects built in Haskell is a fair argument.

          That’s an argument against Haskell being a suitable programming language for certain purposes. Does that make it a bad programming language? I don’t think so, unless you show how that maturity is fundamentally impossible to achieve.

          I also think the criticism of Haskell using its own terminology is valid.

          That’s an argument against Haskell being easy to learn, likely to become popular or influential. Do any of those things make it a bad programming language? Again, I don’t think so.

          The post is just a collection of things the author is unhappy with with regard to Haskell in the broadest sense: the language, platform, ecosystem, community, … At least part of them are plain opinion, another part is unfounded and a few things may be complaints generally shared, but in shades of grey.

          On the whole, that makes it a bad article in my view.

          1. 3

            Yes, there’s pandoc and a few static analysis tools built in Haskell, but IMO that’s a bit of a cop out, since parsers/compilers are trivial to implement in a functional language. None of those projects say much about the effectiveness or benefit of using Haskell to solve more general software engineering problems.

            First of all, it seems easy to dismiss pandoc it is a amazing piece of software (imho). But even without it, the following programs of top of my head may fit the “real world haskell” examples (whatever that means): PostgREST,Nix, the package manager, Dhall, neuron. I don’t really understand why disregarding parser/compilers or anything that is easier to do in a language/paradigm.

            I also think the criticism of Haskell using its own terminology is valid.

            This critic does not stand any ground in the article from my point of view and personal experience. When you work in various domains or scientific fields, each of one as his own idiosyncratic way to express similar or identical concepts due to history, culture, theory currently approved. You construct a terminology and when you learn with it. I think the author has been educated on various OOP languages and internalized this vocabulary as the only way to express something. Creating a network of equivalence between various concept worlds may be bothersome but probably essential to make it your own. Why various variations in French used differents words to speak about the same object? If you can accept the impact of localization on the vocabulary of a language why not in programming language?

            I don’t get the dialectic about “If this language is that old, it must be one of the most used”. Haskell have flaws, qualities and it is just another programming language. I mean Common Lisp may take the same bullet and at the same time have crazy toolings and at the same time a whole other set of issue.

            1. 7

              Nix, the package manager

              This seems to be a common misconception and I’m not sure where it stems from, but Nix is written in C++.

              1. 2

                Corrected, thanks. Seeing too much haskell programs deployed through nix packages, at least for me.

              2. 7

                Yes, there’s pandoc and a few static analysis tools built in Haskell, but IMO that’s a bit of a cop out, since parsers/compilers are trivial to implement in a functional language. None of those projects say much about the effectiveness or benefit of using Haskell to solve more general software engineering problems.

                First of all, it seems easy to dismiss pandoc it is a amazing piece of software (imho).

                Fair point – “trivial” was the wrong word to use there. Building a parser/compiler for a real world language or data format takes a huge amount of effort, and functional languages tend to be particularly good at the types of tree/graph transforms that compilers spend most of their time doing. Functional programming is definitely the right approach to solving the problem, but I’m not sure Haskell provides any advantage over any other language that encourages the functional paradigm.

                That’s my main issue with Haskell. What is it providing that Rust/Swift/Kotlin/Scala/Clojure/F# aren’t? I know the type system is more advanced, but what’s the benefit in that[1]? I haven’t seen a convincing example of a “real world system” that was built faster or with less bugs in Haskell than any of the other functional languages I’ve mentioned. And I have heard stories of how Haskell requires nasty monad transformer juggling in some situations or has difficult-to-spot thunk leaks (which are problems that almost no other languages worry about).

                I agree that every programming language has its own drawbacks, terminology, and specialized domain knowledge. I’m personally even willing to pay the upfront cost of learning that domain sometimes. For instance, I’ve recently been learning J which encourages problem solving through vectorized transforms. But this can result in extremely compact and efficient solutions that require orders of magnitude less code and are faster than the alternatives implementations. That’s a clear advantage, and even if I would never pick J to build a real world system (due to the lack of popularity/support), I’ll pick up some clever new ways of thinking about the problems and structuring the data. Plus it just makes a cool desk calculator :P

                At the end of the day, I write systems to solve problems, and my choice of tools is about deciding what allows me to build it quickly and robustly. For this reason, the majority of the code I write these days is Python/Rust, even though they both have a laundry list of issues that I wish were fixed. I don’t think Haskell is a bad language (and the author could probably do with a less click-baity title, but such is the way of titling rants…). I’m sure if I bothered learning it there’s a lot of internal elegance to the language, but I don’t see a clear-cut advantage to it. Maybe I’ll learn it to build a compiler some day, but there are several other language choices I’d go with first.

                [1] I’ve personally found that whenever I go crazy with trying to create extremely precise types in most languages, I eventually hit a wall in the expressiveness of the type system anyway. I think I need dependent types in some of those cases, but haven’t gotten around to learning Agda or Idris yet, so I usually just reformulate the data structure to make the type constraints simpler, or punt it to a runtime check.

                1. 4

                  That’s my main issue with Haskell. What is it providing that Rust/Swift/Kotlin/Scala/Clojure/F# aren’t?

                  Haskell is a functional programming research language. It served as the playground where programming language theory researchers could experiment with some of the ideas that, when mature, could be adapted by those younger and more strictly production-focused languages.

                  1. 3

                    That’s my main issue with Haskell. What is it providing that Rust/Swift/Kotlin/Scala/Clojure/F# aren’t?

                    Your mileage may vary (besides Haskell, if I am right, being older than all those languages). Do not want to depends on .Net or JVM? Do want to have access to a GC and not manage memory? Honestly, functional paradigm’s mechanisms or idioms percolated in a lot more languages than 10 years ago. For example, I don’t know jack about the JVM ecosystem and as much as I like Clojure or Scala or Kotlin, it is a whole ecosystem to learn to find the equivalent to my non-JVM library or wrapper of choices. We live in a time of choices for most of problem solving we want to resolve, knowing the trade-off and that’s it. It is nice to see the “influence”-ish of the functional paradigm on more recent languages. Do not like the trade-offs you see, choose something next. I will never blame any one saying “I don’t see any advantage for me using this, I will take that”.

                    I relate to your experience. I worked in Python, R, learn in of C++ to edit some program when needed to solve problems at work. But I always looked a bit everywhere to expand my mindset/domain knowledge. I also dabbled a bit with J and it is fun, it is concise and lack of support stopped me on my way too. But it was fun and I don’t see why I will be entitled to rant about J ecosystem or language state. I took my new knowledge and try to see if it helps me to improve my numpy chops. I am no Haskell advocate, my knowledge is mostly read-only but I really like the abstractions proposed by the language. Right now, I settled on the inverse solution of the solving problem approach and decided to learn Raku. It is slow-paced, fun and super expressive. It is my anti-“get the thing done now” because I want to have fun with it (others will solve real problem with it).

                    I don’t have the answers on why Haskell for everything because like you, I don’t think there is one. But if I have to build something similar to pandoc, PostgREST or Dhall, sure Haskell will pop in my mind due to my exposure to them. Maybe it will never fit the bills for you and honestly that’s ok. A hell lot of stuff can be done with Python/Rust with their popularity and communities.

            2. 27

              This sort of article is deeply frustrating to me. I manage a team that develops a Haskell codebase in production at work, and for every engineer that (rightly) looks at this sort of incoherent, imprecise rambling and dismisses it as FUD, many more add it to their mental list of “times when Haskell has made someone quit in anger and confusion”.

              There are valid complaints about Haskell, and its beginner unfriendliness. I made some very specific complaints about its syntax and tooling’s learning curve over in the thread on Hacker News (link: my comment on HN), and I can actually think of two more complaints[1] off of the top of my head this morning. There are definitely valid criticisms!

              But the mysticism of “ooh, types and purity and monads are weird and spooky and Not Actually Good(tm)!” is FUD that is so difficult to evaluate critically, and I think makes folks who would otherwise pick Haskell up in a couple of weeks[2] really afraid to try it out.

              [1] First, type declaration syntax is symmetric to value declaration syntax. This is elegant and beautiful and minimal, but really confuses beginners on what names are values and what names are types. It doesn’t help that values and types have different namespaces, so a can be a value in some contexts and a type in others. Second, Haskell has a very minimal no-parentheses syntax to type declaration. Again, this is elegant and minimal - once you grok it, you understand why they would choose this path to make mathematical symmetries clear - but it’s very confusing for beginners when types, type constructors, and data constructors are not syntactically distinguishable.

              [2] Historically, our internal estimate for onboarding to Haskell is about 6 weeks from zero to production-ready code review. This is not much longer than other languages. However, zero to side project for Haskell is definitely a week or two, and this is definitely genuinely longer than other languages (e.g. zero to side project for Go is like 30 minutes).

              1. 17

                Some parts of this are correct and some parts are not.

                Haskell’s type system, like all type systems, isn’t able to prove much. As I have explained before here, Haskellers should not expect the type of an object to reveal all of the relevant behaviors of the object.

                The author has not yet realized that software needs to be modular at scale. The complaint that they think they’re clever for identifying and griping about, where high-level code needs to export a signature with interfaces, is in fact just part of how modules work. When the author espouses the opinion that we should instead mix and match from a bag of completely interchangeable parts, then they are deliberately forgetting that it is possible for programmers to distinguish between values, which can be composed arbitrarily as long as the type system is satisfied, and modules, which can only be composed according to their declared interfaces. (The author lists Haskell, C++, Python, and Lisp, though, so I could understand if they’ve never developed a rigorous mental model of modularity!)

                Not all abstractions leak. The author probably cannot get their CPU to report voltage levels on each transistor, for example; instead, we are locked behind an abstraction of digital bits of information, and this abstraction doesn’t leak, because the very construction of the CPU is designed to transform voltage-driven transistors into digital logic. Similarly, the author’s Web page is delivered over TCP inside a TLS tunnel. Abstractions might be very complex, but they only leak when we choose to make them leaky, or when we implement them in a metatheory which is not capable of hiding implementation details.

                The author’s claim that Functors are “basically an Object with a internal state changing method” is falsifiable. This claim, known memetically as “functors are containers”, has two well-known counterexamples. In that link, they discuss one of them, the reader monad, whose elements are not data structures but functions. The continuation monad also has functions for elements. In these monads, the fmap method does not transform internal state, but prepends or appends a transformation to a list of pending transformations.

                Callback chains implement continuation-driven control flow. Continuations are the mothers of all monads; in a given language, the possible monads are limited by the possible ways of expressing continuations. Since callback chains are universal for monads in languages like JS, they’re going to arise repeatedly.

                I agree that a language which wants to use monads for control flow should have syntax for supporting their use. Haskell happens to have such notation, though, and I think that maybe the author hasn’t suffered enough through using monads in other languages. Haskell’s notation is much more compact than Python’s or JS’s when it comes to doing asynchronous callbacks, for example.

                1. 13

                  Angertainment.

                  1. 10

                    If something starts out by making the assertion that Clojure has “taken the world by storm”, at least you know where the author is coming from. :) I don’t know if I’ve ever seen a dedicated Clojurist attack Haskellists specifically, so this is interesting from that standpoint.

                    Regarding the complaint about Haskell docs being terrible because they just refer you to academic papers: Well, some Haskell docs are terrible, but also “it turns out” academic papers contain a lot of meaning and are often way better documentation than a typical language would give you. In particular, when I read the original paper introducing Monad to Haskell, it was much clearer than most of the explanations people have written since. Python has PEPs, Haskell has papers.

                    By the way, while you’re looking for examples of people explaining monads badly, keep an eye out for people trying to explain transducers…

                    1. 2

                      I don’t know if I’ve ever seen a dedicated Clojurist attack Haskellists specifically

                      Maybe Not?

                      1. 3

                        Well…hmm… IIRC, in that talk, though he used Haskell in the examples, he’s just looking at a specific type that isn’t unique to Haskell. Besides, he says he made the same “mistake” himself in spec. So hardly calling Haskell a “bad language”!

                        1. 2

                          As I understand it, his problem is that he wants a value to be a member of multiple types, but in Haskell every value can have only one type. That is a pretty foundational aspect of how the Haskell type system works. A language with extrinsic types like Cedille wouldn’t have this problem, maybe he’d like that.

                          It’s not an attack on e.g. Kotlin even though a value only has one type there also, but Kotlin has special syntax to make null handling convenient.

                          My personal opinion is that it is not really a significant problem to fix call sites when a function gets/loses a Maybe in its signature… I’d see it as an advantage since you could optimize the caller, even. If the caller is handling a Nothing that can no longer be returned, I don’t see why that code has to compile.

                          In Clojure, with spec, I believe you can have multiple specs matching a value. So a value can have multiple “types”.

                        2. 1

                          My least favorite video from Rich. I used to use a lot of Clojure and I really like LISP but I would never trade back my ML (F#) to that. Clojure code is much harder to get right the first time and painful to refactor. I usually write Clojure as a quick and dirty if absolutely necessary (like for example no C# driver for something). I think I am going to use Kotlin the next time though.

                      2. 3

                        This is pretty much an article without any merits. Data is just data? Hell, I spent most of my days coercing data into types so that I can:

                        • process data in a reliable manner and handle errors in a meaningful way
                        • store data in an efficient manner
                        • query data in an efficient manner

                        The data is just data people brought us JSON and “unstructured data” that is where most of my pain is coming from. I convert anything and everything I can to typed bytes as fast and as early as I can.

                        1. 2

                          I agree with some of the points in the post, specifically the complains about always using the highest abstraction possible for everything:

                          Part of this has to do with Haskell’s way of tricking people into thinking that more abstraction with higher level types is a good thing.

                          And how these abstractions are taught:

                          Instead of explaining Monads like all other design patterns out there, they insist on using some obscure definition from category theory to explain it.

                          There is value in knowing these abstractions, but much like in code making heavy use of design patterns they just obfuscate the meaning of the code under the pretense of making it more reusable.

                          The other complaints about type-oriented programming and “data has no types” I don’t agree with.

                          1. 1

                            Haskell seems ok as far as pure functional languages go. It just turns out pure fp isn’t actually a good way to program.

                            1. 31
                            2. 1

                              The link is not working.

                              1. 1

                                Check the cached version.