I started using haskell at my last job after having done a couple years of functional programming in scala, but I honestly never found it required that much knowledge of category theory. The FAM trio of classes (functor, applicative, monad) are the most common ideas used from category theory in an explicit way, and they're frankly so prevalent at this point in the industry at large that they're in basically every language in extremely common libraries. Most programmers are pretty familiar w/ map and bind (which is also sometimes called flatMap, then, and_then, or chain). Applicative functors might be a little more exotic, but they're easy to pick up if you understand the other two. And I don't think you really need to understand what a morphism is or how to read arrow diagrams to really use any of these things. If you can use arrays in javascript, you can use the IO monad.
Most of the challenge in haskell for me was figuring out stuff like how I should structure my code to enable mocking out effects for testing (there's multiple answers to this w/ different tradeoffs), or how to get good editor support without ghc-mod breaking. I haven't used haskell in industry in about the past two years, but I imagine these are still some of the biggest challenges w/ using it.
Do you think it would be dramatically improved if Haskell had a bigger community of people contributing user-friendly libraries and tutorials? That was something that made Ruby the perfect newbie language for me. And something I feel is downplayed in Haskell given it's more advanced user base who is a little too obsessed with it's power and demonstrating their knowledge as such, rather than help make it accessible to others.
I can't count the amount of times I came across a popular Haskell library with very little documentation rather than it's type/function API and general blurb about what it does. This is very different that most popular JS/Ruby/Python/etc libraries which include quick-start/getting started/usage examples/etc etc.
Absolutely. I think it's been getting better at that on the tutorial front. For a long time there were very few books I'd actually recommend for haskell, but Haskell Programming from First Principles [1] changed that for me (personally). And I think Stephen Diehl's excellent What I Wish I Knew When Learning Haskell [2] is a fantastic general resource for newbies. But I think the community could stand to have more of this, absolutely.
And I definitely agree about libraries. I'd like to see more haskell libraries with extended tutorials, and written w/ a non-expert audience in mind. I think the community has for so long been dominated by long-time haskell developers and people ensconced in functional programming, much of the documentation is written for those kinds of people.
Make the frequent things easy and safe. And this means syntax should be easy to read and write, documentation should be plentiful and easy to read, easy to start using, even if you are not expert in the area that that particular library covers, etc.
Rust also suffers a bit from this, as more and more libraries are just the generated docs. Here are these 30 structs and 100 impls, godspeed. Yeah, but what is this library, when I would use it? What's the most 100 common use cases?
And a 100 might seem like a lot, but people will chose that instantly works for them. And there are a lot of strange stacks out there. Sometimes people just want the low-level bits of your library. No docs/API for that? Damn. Sometimes people just want to use it as a one-liner, no config files, no import-server-deploy, no binary? Damn.
One often-ignored benefit of constrained languages like Java where there's really only one way to do most things, is that when you get a library you immediately have a reasonable idea of how to use it (given the entity names and types). If a language has a more advanced type system (or none at all), you can't lean on that existing framework and the author needs to do more legwork to explicitly lay out exactly what it is they've made. This doesn't make more advanced languages bad, but library documentation is often neglected and that probably contributes a lot to the inaccessibility of those ecosystems.
On that front, the Monad typeclass is far more general and useful than just for IO and State, so if you are thinking of it as primarily a hack to deal with those, you probably won't get the hype. In addition, it's really useful to work with a large number of examples of different Monad instances (IO, State, Maybe, List, STM[1] if want to get a bit further into the deep end) instead of just staring at the methods in the typeclass and hoping it make sense. It's a pretty broad abstraction, so it will only make sense if you are familiar with what it's abstracting.
[0] https://wiki.haskell.org/Typeclassopedia
[1] http://book.realworldhaskell.org/read/software-transactional...
The case is exactly the same for the Clean language as for Haskell and indeed Clean has Monad instances for all of the types I mentioned aside from STM, so there are no concerns with dealing with those monadic abstractions in Clean. (https://imgur.com/a/sjsDiZq, https://cloogle.org/#using%20Monad) Since IO is Haskell's type that marks impure computations, we can compare Haskell's implementation to the equivalent one in Clean (interface: https://cloogle.org/src/#Platform/System/IO;line=10, implementation: https://cloogle.org/src/#Platform/System/IO;icl)
In Clean, IO is implemented as follows:
:: IO a = IO .(*World -> *(a, !*World))
In Haskell, it is: newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
(for full context see: http://hackage.haskell.org/package/ghc-prim-0.5.3/docs/src/G..., the related monad instance is here: http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GH...)These both implement IO as a function which takes the state of the world as its input and returns a new state of the world as it's output. This is encoded using the state transformation that I mention in the other post (https://acm.wustl.edu/functional/state-monad.php) Both implementations also go on to define Monad instances for their new IO type. The major difference is that the Haskell standard library only exposes bindIO and returnIO to the user and hides the internals of IO from the user and Clean allows the implementation to be a normal library.
That difference is Clean's uniqueness types showing their strength. Clean can explicitly expose it's predefined World type (https://cloogle.org/doc/#CleanRep.2.2_6.htm;jump=_Toc3117980...) to the user with the guarantee that you can't write a function of type IO a -> a because it would violate the uniqueness properties and thus be a compilation error. Haskell instead uses the module system to keep State# RealWorld from being exposed to the user. This means that if you as a user want a different set of abstractions for impurity in Clean, you can build from the World level rather than needing to construct it out of what can be done with bindIO and returnIO. For details on what's going on with State# see https://www.fpcomplete.com/blog/2015/02/primitive-haskell
From the perspective of "the value prop for learning/using monads", this discussion leaves us in a worse place than where we started because the conclusion is that uniqueness types aren't a get out of monads free card and that Clean uses the many of the same Monad-related abstractions as Haskell does and uses them for the same purposes. In order to not leave you out in the cold as to the value prop for the monad abstraction, you can see how it works for a number of different Monad instances in Tikhon's answer on Quora (https://www.quora.com/What-are-monads-in-functional-programm...), though he chooses to use join, fmap, and return as the fundamental parts of a Monad, rather than bind and return, as I have here. As he touches on in his discussion, it's common and straightforward to implement one definition in terms of the other, so anything you learn from about that definition can be ported the definition I use without much fuss, so don't worry if it doesn't match at first. What this means is that if you have a tools in the standard library that only depend on features of Monad, you can use the same small collection of functions to solve a ton of problems.
I expect to be coming back to this comment and the references quite a few times until it clicks for me.
Without monads? Not pretty far, but they're far simpler than the wide web would have you believe.
Without category theory? Sky's the limit. I say this as experienced Haskell programmer occasionally dabbling in category theory for funsies. The practical impact on "how easy is it to program Haskell" of category theory is basically zero.
What i'd love is an imperative language where you declare what effects a method can have and the compiler enforces them. E.g. if it promises not to mutate any parameters, it can only call functions that make the same promise etc.
http://docs.idris-lang.org/en/latest/effects/depeff.html
readInt : Eff Bool [STATE (Vect n Int), STDIO]
[STATE (Vect (S n) Int), STDIO]
http://docs.idris-lang.org/en/latest/st/machines.html logout : (store : Var) -> ST m () [store ::: Store LoggedIn :-> Store LoggedOut]
They're both implemented within Idris, as libraries/modules, rather than being compiler magic:- https://github.com/idris-lang/Idris-dev/blob/master/libs/con...
- https://github.com/idris-lang/Idris-dev/blob/master/libs/eff...
I think it'd be possible to write similar effect systems in other dependently typed languages like ATS, which is a relatively imperative language (C+ML-like).
Typescript cures most of the JS ills. Sure TS is more akin to Java/C# and not the much better Haskell type system. But it is good enough and catches 99% of the real world problems of naked JS.
To me Haskell is training for your brain. Once trained you are a better JS/C#/Java/C++ programmer.
I could go on about the economics of getting a Haskell job:. Haskell and Elm developers are taking a paycut compared to what they would earn if they used any language. Even if they are paid well they could get paid more. Supply/demand at work there.