12 ms·
I'm really curious why Haskell has seen so little adoption in industry. Is it just the difficulty? Or a chicken-and-egg effect with tooling and libraries? One
by _bxg1 7y ago
I'm really curious why Haskell has seen so little adoption in industry. Is it just the difficulty? Or a chicken-and-egg effect with tooling and libraries?
One thing I've wondered is if it actually isn't ideal for a lot of cases. FP is beautiful for certain things. But in some domains (or pieces of domains), state and mutation aren't just unfortunate implementation details, but a core element of the problem space. For these cases, the FP answer is usually "recompute and replace" (generally with immutable data structures that make this efficient). This can be syntactically clunky when it's a major part of your application, and not just a necessary evil to be swept out to the edge. The most successful languages let you be pure-functional where it makes sense and then stateful where it makes sense. Haskell doesn't, really (from my cursory reading about it).
- develop7 7y ago> Is it just the difficulty? It's loads to unlearn for most of programmers and a perfectly natural knee-jerk reaction of a refusal to. I mean, the more one knows already, the more is the desire to reuse such knowledge. Well, at least I have been there. > Haskell doesn't, really (from my cursory reading about it). Of course it does, https://en.wikibooks.org/wiki/Haskell/Mutable_objects https://en.wikibooks.org/wiki/Haskell/Mutable_objects looks a good start.
- tathougies 7y agoI havr never noticed immutable data structures to be more difficult to deal with. For the most part, because of monads and effects and such you can essentially write better imperative code in haskell. Im noy sure why youve decided that haskell is incapable of the syntactic appearance of mutation.
- _bxg1 7y agoTo be fair I haven't really used it, only read the core of the guide, so I may be mistaken. But I've done a bit of Clojure, and I've done a bit of Immutable.js, and particularly when you have a deeply-structured piece of data, "mutating" something a few levels down gets really ugly. Now, maybe something about Haskell Enlightenment obviates this case entirely in a way I'm not seeing. But I also remember Haskell seemingly forcing you to push all your imperative code up to the surface layer of your otherwise pure program, which sounds great unless you need to do really meaningful things that are by nature imperative.
- jerf 7y ago"Now, maybe something about Haskell Enlightenment obviates this case entirely in a way I'm not seeing." Many times the answer is that with a different structure you don't need deep mutation to be a critical part of your program. After all, "deep mutation" isn't considered a great idea in object-oriented languages either, where it constitutes a violation of the Law of Demeter [1], either in letter or in spirit (i.e., creating a chain of methods to set some deep value may in letter follow the Law but can still be a violation in principle). But if you do need it, Haskell does have a rather nifty mechanism for mutation patterns to be first-class elements themselves through "lenses", which capture as a first-class value some access pattern and mutation pattern on a given value. And while one of its original purposes is to allow Haskell like value %~ property1 ^. property2 =. newValue such that in a monadic context that will pretty much do what you'd expect as an imperative programmer, it also means (property1 ^. property2) is itself a value that can be used and passed around like any other, and allows for things like creating generic functions that take "a thing, and a thing that will extract a Name from that thing, and will return a new copy of the original thing with the name all uppercase" or something like that. And there's a whole bunch of other ways to make that stuff sing and dance too, if you're in the mood. You can even do really melty stuff like have a lens that will expand an int into its bits, allow you to manipulate those bits as if you had an array of bool, and then will re-pack them into the int for you. Lenses can take any arbitrary slice out of an object as long as you can express the extraction and the creation of a new object putting the stuff back, and then they can be composed together as-needed. It can be powerful, but it can get pretty brain-melty too. [1]: https://en.wikipedia.org/wiki/Law_of_Demeter https://en.wikipedia.org/wiki/Law_of_Demeter
- _bxg1 7y agoI hadn't seen that kind of thing; that's good to know about
- rbonvall 7y agoLet me add that lenses are not just a Haskell thing. It's a simple (and beautiful IMHO) concept from functional programming that can be introduced in many languages. Also, you can have lenses without the cryptic operators.
- thrwayxyz 7y agoYou're lucky enough if you can find a developer who knows mutable data structures outside of SF. If you want immutable ones you need to add a zero to their wage. Most shops aren't prepared for that.
- gilbetron 7y ago> You're lucky enough if you can find a developer who knows mutable data structures outside of SF. That's one of the most arrogant statements I've read on HN in quite a while. Nearly all developers know mutable data structures, it's bread and butter. Immutable ones aren't some exotic life form, it's just that using them effectively (read: efficiently) as mutable ones can be really tough, and leads to more complex code. You should maybe get out of SF for a bit.
- thrwayxyz 7y agoI am out of SF. The number of times I've seen people start trying to parse XML with regular expression tell me all I need to know about their ability to code.
- whateveracct 7y agoI've had random interns enter a purely functional codebase with 0 FP background. With a normal amount of onboarding, they were using immutable data structures with ease.
- namelosw 7y agoYou probably should take a visit to UK. Standard Chartered has been a Haskell shop for a long time. There are some others in London I think. And both England and Scotland have many universities teach Haskell. Let alone GHC and Idris were born in Scotland.
- dmix 7y agoIt's 100% the difficulty. Anyone saying otherwise is lying because they want Haskell to be popular, adopted it very early on in their career when they could really invest in it, or is a natural at this type of stuff and simply doesn't know any better. I've learned about 10 different languages now and Haskell easily had the highest learning curve. Most languages I was able to get semi-usable in within a couple days, at least to do some minor stuff that works. But Haskell was a real commitment that took months until I was comfortable doing real stuff. You have to learn about how to mutate data and how to manage state using monads and functors, how to query through complex objects using lenses, even getting it to parse some complex data coming from a JSON feed into a usable form requires a good understanding of the type system. But ultimately besides when I first learned Clojure (my first exposure to FP), I don't think there's a language that has taught me as much about programming as Haskell. It was very rewarding and something I still continually dabble with and learn from on the side. I've yet to pull the trigger and actually build a full side project with Haskell. Which is typically my biggest test. I've found Erlang/Elixir to be the far better middle ground from my day-to-day work in Ruby/JS when I want something modern, fast, and functional. Once PureScript becomes stable I have a feeling I'll be diving harder into Haskell and may finally make that full commitment it requires for a real project.
- _bxg1 7y agoYou seem like someone who could answer this: why use PureScript over Elm?
- dmix 7y agoHonestly I've never fully given Elm enough of a run-through to say yet (ditto with OCaml). I remember 2yrs ago I was evaluating it but decided to learn React/Vue.js for professional reasons. Additionally I wasn't convinced that Elm would be an ideal long-term commitment and more of a compromise between JS, FP, FRP (functional reactive programming) and more of a framework competitor than a full-blown language. While I see PureScript as a full long-term language-level commitment to Haskell style FP minus the purity. But again my exposure to it has been too limited to have a strong opinion.
- garmaine 7y ago> The most successful languages let you be pure-functional where it makes sense and then stateful where it makes sense. Haskell doesn't, really (from my cursory reading about it). This is absolutely wrong. Sorry to be so direct, but I want to make sure other people not familiar with Haskell don’t get the wrong impression. Haskell is explicitly designed to separate purely functional and stateful code with a clear interface between them: monads. It does exactly what you are asking for.
- thrower123 7y agoWhenever I've used Haskell, the monads infect things like a virus, similar to the way async/await metastasizes across a C# codebase. Note: I am not very good at Haskell.
- smackmybishop 7y agoProbably because async/await IS a monad. Avoiding that infection just takes some design experience.
- lmm 7y agoThat's what happens when you're working in a pervasive-mutability-by-default (or pervasive-IO-by-default) language as well - your whole codebase is full of hidden state mutations and hidden interactions with the outside world. You just don't have any idea where they're happening. You can write Haskell in the same style with monads everywhere and you're in essentially the same situation (just with more visibility into it) - but then you can actually start isolating the parts where mutation or outside interaction happen, and separating them from your core business logic. Which is the same thing you'd do in a high-quality codebase in any other language, but in Haskell you can do it in a way that's actually enforced and visible rather than just convention.
- chas 7y agoSorry for the additional pedantry, but I think this important to be precise about given the target audience of your comment. Monads aren't the separation between purely functional and stateful code. The Haskell type system maintains that separation. Anything that's doesn't return IO a for some a appears to be a pure function from the perspective of the programmer. Once a function returns IO a, there aren't any* functions provided by the compiler that can make a function that uses those results not also return IO b for some b. For example, the type of getLine is IO String (because it impurely produces a String) and the type of putStr is String -> IO () (because it takes a String and mutates the world without returning anything). If the compiler provided a function for computing on the a in the IO a, for instance, bindIO :: IO a -> (a -> IO b) -> IO b and a function to wrap the results of non-IO functions, such as returnIO :: a -> IO a, you could do arbitrary computation with these IO-wrapped data types, but know at a glance if your functions were impure. This approach doesn't require the Monad typeclass at all, just a magic type called IO that tags impure computations that are implemented with compiler and runtime magic. It happens to be the case that this is exactly how GHC implements the IO type. bindIO is implemented here[0] and returnIO is implemented here[1] and the compiler magic used to implement them isn't* exported, so all IO operations have to go through those functions. It is not a coincidence to that these functions have the right types to form a Monad instance for IO and indeed, that is also present[2], but the IO type and the type system that ensures it can't be sneakily hidden are doing the heavy lifting, and the Monad instance (and accompanying syntactic sugar), are just there to make it nicer to work with and easier to abstract over. If you have a passing familiarity with Haskell, the phrase "state monad" is the obvious place where my claims stop making sense. In fact, the State type only supports computations that are entirely pure. If you want to simulate global variables in a language that didn't have them, you could always pass all of your global variables to every function and get updated ones back from the function along with the nominal results of the computation. The State type is just a regular data type that wraps stateful functions constructed by such state passing. A type of the form State Int String is just a function that takes an Int and returns and String and an Int, no compiler or runtime magic needed. You can play the same trick as in the IO case and provide functions bindState :: State s a -> (a -> State s b) -> State s b and returnState :: a -> State s a in order to compute on these "stateful" values while making sure the result state got passed to the next function in the chain correctly. Like IO these two functions can be used to create a Monad instance for State. Unlike IO, State is just a data type holding a regular Haskell function, so it's extremely reasonable to write a function of type State s a -> s -> a which runs the State s a computation with an initial value of type s. This is written by unwrapping the State type and then passing the initial state value to the function inside and return the result while ignoring the returned new state. More details on how State is implemented are available here[3]. A complication to this is that if you want stateful mutation for performance reasons, the ST type[4] also exists, which looks identical to the State type from the programmer's perspective, but plays similar tricks to IO in order to actually mutate under the hood while not exposing the implementation details to the user, so it can be reasoned about exactly as if it was pure and using the same implementation as State. These Monad instances for IO, State, and ST start to pull their weight when you write functions that only use features provided by the Monad typeclass and they work seamlessly with any implementation of stateful computation despite their very different internals. Monad is quite general, so if all you care about is abstracting over stateful computations, you can also use the methods from MonadState[5] which allow you to interact with the state along with the results of the computation independent of the implementation of stateful computation. * In the name of not getting bogged down in details, there are a few parts of this discussion that are not entirely accurate, particularly around functions like unsafePerformIO[6]. [0] http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Base.html#bindIO http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GH... [1] http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Base.html#returnIO http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GH... [2] http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Base.html#line-1363 http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GH... [3] https://acm.wustl.edu/functional/state-monad.php https://acm.wustl.edu/functional/state-monad.php [4] http://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Monad-ST.html http://hackage.haskell.org/package/base-4.12.0.0/docs/Contro... [5] http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html#g:1 http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Mo... [6] http://hackage.haskell.org/package/base-4.12.0.0/docs/System-IO-Unsafe.html http://hackage.haskell.org/package/base-4.12.0.0/docs/System...
- llamathrowaway 7y ago> But in some domains (or pieces of domains), state and mutation aren't just unfortunate implementation details, but a core element of the problem space True, but I would argue that it is far, far more common for people to writing stateful code to do things that are better done in functional style, than the other way around. This comes from my own experience of learning functional programming in JavaScript (before knowing about Haskell et al) and refactoring a project into a functional style that relies heavily on immutability. I think Haskell is not more widely used in the industry because it has a very academic reputation. If you say you write Go, people think you are a practical programmer who turns coffee into solid business logic that powers some profitable website. You write Haskell? Then you are more likely to be perceived as some eccentric scholar or their like.
- _bxg1 7y ago> I would argue that it is far, far more common for people to writing stateful code to do things that are better done in functional style, than the other way around. For sure. But still, there exist cases. Many of them in JavaScript, actually. In my JavaScript UIs I relish every opportunity to write something as a pure function. But I also need to manage a lot of deeply structured, non-homogenous state that's genuinely meaningful to the application. Separating the two is crucial, but both exist. I've really enjoyed MobX, as it allows you to make the most of both types of programming and hook them up together in a cohesive way. > I think Haskell is not more widely used in the industry because it has a very academic reputation...you are more likely to be perceived as some eccentric scholar or their like. And yet Clojure has gotten traction :)
- Ixiaus 7y agoI actually think it's seeing quite a bit of adoption in industry. What I'm seeing is a class of developer that won't learn it or thinks they can't learn it, of course "to each their own", but I truly think Haskell/PureScript/Idris/Agda are onto something remarkable: making the software industry more like an engineering discipline and less of a craft (i.e. like the difference between civil engineering and carpentry). Your argument RE: immutability and purity hampering implementations: Haskell excels at allowing developers to start with impure IO-heavy code, allowing you to later refactor chunks of the implementation out to pure code. In-fact, I talk about Haskell as the language you use to "move fast and _not_ break things". It also encourages a more principled approach to software design and reasoning than many other programming languages. I've used Haskell (and seen it used) in production for many different problem domains for the last seven years of my career. I have yet to see something Haskell/GHC cannot handle well with a few niche exceptions. In my time using Haskell I've come to think of "mutation" as a cardinal sin in software and you better have a good reason for committing it instead of letting the compiler do it for you (you can write mutable code in Haskell, too, btw - it just strongly discourages you from doing so and it makes some classes of mutable code impossible to write, which is a very, very good thing). As a (very) fallible generalist, Haskell is a godsend and we use it extensively where I work for shell-scripts, for code generation, for (performant) network packet parsing, HTTP web servers, gRPC micro-services, and even our "build bot".
- _bxg1 7y agoHave you used it for anything interactive? All of the above seem to me like natural fits for a pure functional style
- Ixiaus 7y agoI think you mean, by interactive, something with a user interface like a gui. First, see functional reactive programming. The only project I used it for that was interactive in that sense was an interactive CLI tool. However Oskar Wikstrom wrote a screen cast editing tool so he could make his Haskell screen casts. I don't think functional style prohibits interactivity (see: purescript which is strongly influenced by Haskell, we use it for all frontend web work now).
- simplecomplex 7y agoVery few programmers are proficient in Haskell, and operating systems and language tooling are built around imperative C-style semantics. Combine that with the fact that most of the software industry does not care about correctness or stable software and generally lacks professionalism. "Just ship this half-assed software as soon as possible" is the attitude at the majority of software companies.
- baroffoos 7y agoHonestly this is true. Most of the world doesn't give a shit if a page on their web store is broken. They get an exception email and then fix it, no real loss. While switching over to haskell may make your software more stable, at the end of the day the amount of extra time spent writing it in a more stable language is going to cost the business a lot more than a slightly buggy website will.
- yakshaving_jgt 7y agoCompletely false. Many “real world” businesses are shipping web apps in Haskell. Anecdotally, they take less time to write than the equivalent Rails app.
- jinfiesto 7y agoI don't know. I've been slinging Haskell on the side for the better part of a decade and do most of my day to day in RoR (trying to start moving clients over to Elixir/Phoenix.) Haskell is an amazing language. I would totally buy that Haskell teams probably win in the medium to long-term as the wins you get in terms of support/maintenance/extensibility are pretty obvious. However, anecdotally, Haskell forces me (and I imagine other programmers) to invest a lot more time up-front into getting your design in order. Haskell punishes an "oh I'll just hack that out" attitude pretty badly. Which, as I said above I would completely believe leads to wins in the medium to long-term. If I need to bang out an MVP over the weekend, I'm probably not choosing Haskell unless it's well-trodden Haskell territory. Additionally, while the language itself is amazing, the ecosystem has issues (enumerated in the article.) Tooling sucks, there aren't enough examples of people doing normal things, there are frequently not libraries for basic things, obviously integrations with popular services are lacking, and the list goes on. When Haskell has a decently mature and actively developed web framework that has reasonable docs, examples, and a not pathetic ecosystem (by the standard of modern web frameworks) I'll happily jump into using Haskell in production. Unfortunately, these aren't things enough of the community seems interested in to have significant movement on. Servant looks very interesting with regards to what I'm looking for, but I'd be lying if I said I understood the types.
- kartickv 7y agoMy theory is that the FP folks would have seen more success had they figured out ways to bring their features to mainstream languages, rather than asking people to adopt wholesale their weird languages (from an average programmer's point of view). For example, why can't I annotate functions as lazy? Swift takes one step in that direction, with lazy var, but why not a lazy func or lazy class? Even the lazy var can't be used for local variables. People are generally more willing to accept incremental changes than an entirely new way of doing things. For good reasons: they're skeptical, availability of talent, tools, libraries, IDEs, help if they run into trouble... An analogy is the spread of yoga in the west the past decade or two, because it was easy to do so without changing your lifestyle. If Westerners were asked to fly to the Himalayas for a month to learn yoga, how many would have learnt yoga?
- thrower123 7y agoThis seems to be the path that the C# language team is on, one step at a time, boiling the frog slowly.
- zzzeek 7y agoPython has tons of functional features [1] while not being a purist FP by any means. This article liked to say quite often that "X would be impossible in Go or Java!" and I kept thinking, "I bet it's possible in Python, just not as academically wonderfully as you were hoping". As it turns out, Python continues to be one of the top three languages in terms of popularity. It's not clear if this has helped feed a bigger userbase into purist FP languages though. [1] https://docs.python.org/3/howto/functional.html https://docs.python.org/3/howto/functional.html
- froogle 7y ago> My theory is that the FP folks would have seen more success had they figured out ways to bring their features to mainstream languages, rather than asking people to adopt wholesale their weird languages (from an average programmer's point of view). I'd argue this has been happening for years and years now. If you want a pithy saying, you could say that over time languages become closer and closer to Haskell. Option types, pattern matching, pure functions (see: Vue/React with computed properties, or any other frameworks doing things close to functional reactive programming), type inference (even Java is getting a var keyword!), more powerful type systems (things like the Typescripts of the world have) are now becoming trendy, but Haskell had them years and years ago. The above is definitely oversimplifying (a short HN comment is no place to get into the fundamentals behind the various kinds of type systems), but I've found all the things I love in Haskell and other FP languages seem to slowly drift on over to other languages, albeit often a little suckier. (I'm still waiting on software transactional memory to become mainstream, though. Of course, in languages that allow mutable state and without some way to specify a function has side effects, you're never gonna get quite as nice as Haskell. Oh well.)
- AnimalMuppet 7y ago> But in some domains (or pieces of domains), state and mutation aren't just unfortunate implementation details, but a core element of the problem space. For these cases, the FP answer is usually "recompute and replace" (generally with immutable data structures that make this efficient). It can get worse than that. My problem space has mutable state that is shared between multiple threads. FP's initial answer is "shared mutable state is evil". And they're right! But if that's the nature of your problem, then you're kind of stuck with it. But the problem with the "recompute and replace an immutable data structure" is that I now have to notify all the relevant threads that they need to replace their reference to the data structure (avoiding race conditions in the process), and that seems at least as nasty as the problems I have doing it the imperative way.
- brianberns 7y agoYou might be interested in software transactional memory: https://en.m.wikipedia.org/wiki/Software_transactional_memory https://en.m.wikipedia.org/wiki/Software_transactional_memor.... I believe it addresses some of the issues you mentioned in a functional programming way.
- AnimalMuppet 7y agoInteresting! But in my world (embedded systems), those I/O writes aren't just writes to a file or a network socket. They're writes to device hardware, which has to be in the written-to state the next time that another thread interacts with it. That is, the I/O operation has to be part of the transaction, not queued up to run after the transaction commits. Still, this approach goes farther than I thought possible to solve the problem...
- brianberns 7y agoYeah, embedded systems isn't a domain where functional programming is going to work well. Good luck with those locks! :)
- mbrock 7y ago
- dev_dull 7y ago> even getting it to parse some complex data coming from a JSON feed into a usable form requires a good understanding of the type system. This is a good litmus test for the usability of a language. There’s no reason parsing json should be difficult.
- hesselink 7y agoIt isn't, I don't understand where this comment comes from. You can derive the entire thing without writing a line of parsing code.
- jhayward 7y agoThe learning curve is one thing; dealing with purity and immutability is another. But the real stumbling block (besides the tooling issues) is the effect of lazy evaluation. Lazy evaluation can make it quite difficult to reason about the time and memory resource requirements of Haskell programs, and debugging those isn't a whole lot of fun. It is do-able, and like anything, gets better with experience, but it's hard to push things to production when you aren't sure they won't OOM or capriciously start doing some long thunk chain evaluation.
- _bxg1 7y agoDoes it have trap-doors for optimization like Clojure's transient data structures?
- weavie 7y agoThere is unsafePerformIO, but it's generally considered a really bad idea unless you really know what you are doing, and even then it is probably a bad idea. It is useful for debugging though and putting trace statements in.
- hardwaresofton 7y agoIf you'll forgive the analogy, Haskell is kind of like the Mercedes of production-ready research-grade languages. You may not actually use haskell, but the features that haskell is pioneering are what you'll see trickling down into other languages, as language designers look over and borrow things. Some examples (though they're not all invented by haskell, but haskell has popularized them IMO): - non-nullable types - immutability as a default - typeclassses + structs - abstract data types - errors-as-values - monads Haskell or any other ML language didn't come up with all these things of course, but Haskell is one of the best languages Take a look at rust -- it's basically got a near haskell-grade type system (and there are lots of ML languages with more flexible type systems than Haskell as well), with C++ like performance. It would have been a lot harder for rust's designers to incorporate such a nice type system without the exploratory work haskell did and continues to do. All that said, I'm pretty sure Haskell is seeing little adoption because of the learning curve. > The most successful languages let you be pure-functional where it makes sense and then stateful where it makes sense. Haskell doesn't, really (from my cursory reading about it). Haskell almost certainly does this, this is actually one of the best features of haskell -- it lets you do functional things and stateful things separately and encourages you to keep them separate.
- ookdatnog 7y ago> - abstract data types I suppose you meant to say "algebraic data types"? (which have been adopted by Rust and Swift, and even the C++ stdlib)
- lmm 7y agoC++ doesn't actually have ADTs. std::variant is not a true sum type (1 + 1 + 2 = 3, so to speak).
- mwcampbell 7y agoCan you please explain further why std::variant is not a true sum type?
- nstart 7y agoCannot speak for industry, so speaking from experience in academia when we were learning functional programming (FP). The key difficulty there is the paradigm shift in thinking. For most people our thinking matches imperative programming. Ask a person to do something like run an analysis of an accounting book using paper, pen, and a calculator, and you'll see them keep some tallies which they keep updating as they go along. Even if there was a way to convert their work into a method which just involves repeatedly tapping out the numbers into a calculator in a formulaic way, almost every time it's going to be easier to reason about the logic in terms of stored state and progressive steps. When you get hit with the paradigm of functional programming, which is beautiful when it works btw, you need to switch your thinking from pure logic to formulae driven logic. That's an unnatural shift and given how poorly early schooling helps shift our thinking to that mindset when we do maths, it's a hell of a leap. Anecdotally we had a couple of pros at math - people who understood the fundamental beauty of math and proofs - and they took to FP like ducks in water. Even when we built a library management system in Haskell.
- voidhorse 7y agoI think Haskell actually has a few qualities that can potentially turn people off at different points, all of which have been mentioned by others: * Lazy Evaluation -- usually becomes an issue at some point if the project isn't trivial. * Lack of dependent types -- while Haskell's types system is great, this is a missing piece that proves a sore absence for some. It's not very surprising that several functional languages developed after haskell, inspired by haskell, and implemented in haskell (idris, agda, coq) * category theory -- While you can get by plenty well just knowing a few basic abstractions from category theory, it's true that many libraries rely on highly-theorectical concepts, and that a solid portion of haskell development efforts are still tinged with an academic flavor. Just take a look at some of Edward Kmett's coding videos--he typically has one (or several) mathematics/highly theoretical comp sci papers open in one window, while in the other he's implementing a hugely popular library like lens. This sort atmosphere of academism turns a lot of people off. It pegs the language as a theoretical exercise from the get go, and plenty of people are either don't believe in the value of theory or are far too busy to take the time to dive into how it applies to their situation. I think the academic veneer around haskell is its biggest weakness when it comes to adoption, but that's said, it's still had more success than a lot of other academic, purely functional languages thanks to the efforts of core researchers/users/contributors to break it out of the ivory tower. The ideas are good. Almost every other modern programming language has stolen concepts from haskell at this point--so in some sense even though it's still somewhat niche its influence is practically ubiquitous (just take a look at the list of languages its noted as having influenced on wikipedia! https://en.wikipedia.org/wiki/Haskell_(programming_language) https://en.wikipedia.org/wiki/Haskell_(programming_language)). In a broader sense, the functional programming paradigm has proven not only that it's a viable one for industry applications, but often superior to object oriented or imperative techniques when it comes to fidelity of expression and preventing bugs. If nothing else, haskell is great because it provides a fairly rigorous environment in which you can explore functional programming concepts, which you can bring with you to almost any problem and any language and manage to derive some benefit.
- solidsnack9000 7y agoIn fighting games, characters are sometimes described in terms of their “skill cap” and “skill floor”. The “skill cap” is how well you can play, if you really invest in this character. The “skill floor” is about how bad things can get if you don’t play that well. Some characters are very approachable and easy to play. If you don’t know what you are doing, it’s alright — you can muddle through. If you play them in a really exceptional way, it doesn’t make all that much difference. Some characters are really tough to play at all; and once you figure it out, they aren’t particularly exceptional and don’t reward further investment. A “high skill cap” character is one where you can keep learning and learning and your performance at the game will actually get better and better. Some of these characters are also approachable — they have a gentle learning curve. Some of these characters are basically unplayable until you can play them really well — there is an inflection far to the right where you go from dying all the time to actually winning a fair number of matches. Haskell is like one of these characters. Until you’re really good and know a lot, you’re basically going to ship nothing. This effect is sort of invisible to senior programmers learning Haskell because they are already so skillful and are used to having to skim a CS paper or two, once in awhile, to be able to get their work done. Once you are good at Haskell, vistas really open for you in terms of the kind of programs you can design and build. Many year after setting it aside, I still rely on what I learned about Haskell API design and effects modeling to design reliable, transparent and modular distributed systems (it all starts with the types). “High skill cap” characters tend to be admired, but not frequently played.
- yakshaving_jgt 7y agoI have never read a CS paper. I do not know Category Theory. I failed high school maths. I run three business on Haskell.
- tasuki 7y agoNice. Tell more?
- yakshaving_jgt 7y ago
- PeterisP 7y agoFor me, the reason why I abandoned Haskell (for a couple years I was writing about half of third projects in it) is the complexity associated with laziness. FP and immutable data structures and monads are cool and mostly understandable once you grasp the concepts, but laziness is a double-edged sword. Laziness is cool, it enables a lot of nice things, but it makes me unable to easily reason about space complexity of any nontrivial algorithms, and that repeatedly bites me when I have to write such code. In imperative code, space complexity is obvious and explicit, time complexity is intuitive for me, and correctness is shaky and needs to be tested. In Haskell, correctness tends to be obvious (if there are no typos causing syntax to fail, it almost always gets the exact result I intended 100% correctly in the first try), but the space and time taken by the algorithm may be and often is surprising to me; If I make tiny modifications to the code, the execution may suddenly explode from 0.001 second to an hour because suddenly processing n entries involves creating and disposing n^2 thunks, taking all available memory and extreme amounts of time. And despite trying a bunch to wrap my head about it, it keeps happening to me, it's just not intuitive to me - for me, eyeballing efficiency and exact time/space execution of a nontrivial Haskell function is just as hard as eyeballing whether random C code does everything correctly without a memory leak or overwriting being possible in an edge case. I also have trouble with Prolog for the same reason.