At the risk of sounding inflammatory... I would be willing to believe that purely functional languages are the "one true way" if there were even the slightest bit of empirical evidence to support it. But where are all the successful large scale projects built with Haskell (or Clojure or whatever)?
The biggest FP project I was aware of was Twitter using Scala and they ended up completely backing away from it. Yikes.
The only other popular site that springs to mind is Hacker News, and frankly, it sucks. It's practically the Hello World of discussion forums.
The truth is, at the end of the day almost everything is being built with Java, Python, Ruby, or JavaScript. Can you really blame the product owners for being wary of writing their whole product in a functional language?
> But where are all the successful large scale projects built with Haskell (or Clojure or whatever)?
How about Erlang. Let's try it, just from the top of my head:
* AXD 301 Switch -- Classic. Powers and control phone switch networks of whole countries. Claims 99.9999999% reliability.
* Basho Riak -- popular NoSQL database, highly scalable nodes are peers
* RabbitMQ -- popular message queue used by enterprises
* WhatsApp -- messaging application, processes billions of messages a day. Built and maintained by only a few engineers. Sold for billions of dollars.
* Klarna -- European payment processing
* Bet365 -- Sports bets
* Stock trading -- Allegedly Goldman Sachs uses it.
* Erlyvideo.org -- Video streaming service
* eNodeB -- Ericsson cell to internet gateway. There is a 50% if you want to look at cat pictures from your smartphone and Erlang breaks, you won't see your cat pictures.
* Wings3D -- A subdivision 3D modeler. I guess you can build your 3D cat and then send it over WhatsApp via a eNodeB to your friend.
Those are just I know of. So there you go. Maybe you should learn Erlang ;-)
> How about Erlang. Let's try it, just from the top of my head.
Erlang isn' purely functional language in the same sense as Haskell is. It's much more mainstream compared to it.
Clojure has even less of it. It's basically LISP which is about 60 years old.
Well OP asked about Clojure so Erlang fits the profile.
But you make an interesting point in a way. One can ask, ok here are two non-strictly functional languages that seem to be fairly practical. Used for large distributed mission critical systems.
Would they be better off written in Haskell?
Would they have been written at all if creators only knew about Haskell?
How large is the relationship between fault tolerant and safe systems as a product vs strong compiler type safety in the language it was written.
>But you make an interesting point in a way. One can ask, ok here are two non-strictly functional languages that seem to be fairly practical. Used for large distributed mission critical systems.
I think there're at least these problems with Haskell:
* The language is badly designed. See the number of extensions which aren't standardized but widely used. See also obvious problems such as requirement to use renames when importing code, and problem with record names conflicts which isn't solved for years.
* The focus of the language isn't correct. Lazy evaluations creates a lot of problems both in program performance and complexity of the compiler. The most important parts are pureness and side effect control.
* The language is already obsolete. Many its constructions and related complexities are redundant if we unify type and expression level, and get as a result dependently typed system.
I hope some language in the future will implement these ideas, and we will have a widely used pure functional dependently typed language with explicit control of effects.
I see two candidates for such a language:
* Pure script - it's Haskell done right, compiledd to JS. Unfortunately, it doesn't support dependent types.
* Idris - it's the language which I describe, but I fear that it's impossible to create a widely used commercial language without major industry players' support.
> the number of extensions which aren't standardized but widely used.
Actually, I think this is something that Haskell did right. It allows experimentation with new language ideas in a way that allows them to be tested safely with existing codebases. Edward Kmett recently had this to say about it:
> I appreciate Haskell's willingness to take a very very long view, and explore the design options, before committing to a path. In many ways, it is this feature of our community and our language that keeps other programming languages looking to us for features and designs to steal.
> The language is already obsolete.
By that argument so are C, C++, Java, etc. But it's about the existence of a mature ecosystem, not about what is theoretically known.
> Pure script
PureScript is great, but its compile to JS basis makes it inappropriate as a general purpose language.
> Idris
Idris looks promising, but it doesn't have a large enough ecosystem yet. I would certainly be willing to switch from Haskell to Idris in the future, but Haskell already is at least a little bit dependently typed [1] and as hinted at above I wouldn't be surprised if Haskell is able to continue improving its dependent typing capability as research advances.
> PureScript is great, but its compile to JS basis makes it inappropriate as a general purpose language.
Except that Javascript is rapidly making inroads on everything except systems programming. If Java is a general purpose language (can't be used for systems without translation due to the JVM), then so is anything-which-compiles-to-JS.
I think the really important thing is that, while I've been enthusiastic and interested in Haskell for a long time now (~8 years?), the vast majority of people will never understand even a comparatively simple concept like monads, let alone anything higher level than that.
Until you can 'get work done' without the equivalent of graduate-level math classes, there's simply no way to develop that 'mature ecosystem' that everyone is hoping for. People have been using 'better if you understand the complication' languages for a long time now, and there's a good reason they're still niche, unfortunately.
Erlang is a great language, but it's very definitely not of the same scale of difficulty to understand as Haskell. You can noodle around with Erlang and end up with something that works reasonably well - in my experience with Haskell, if you can't mathematically formalize what you're talking about, you're going to have a bad time, unless you do go the 'embedded scheme interpreter' route, which is a fun project, but why not just use Racket to begin with?
Until you can 'get work done' without the equivalent of graduate-level math classes
The problem is the name "monad", not the concept itself. You don't actually need to know anything about category theory to do I/O. You just need enough exposure to the concepts to know why the Monad type class is so repeatedly relevant as to be given a named abstraction.
People have a hard time getting past the name. You don't need to be a category theorist to use monads in Haskell.
> You don't need to be a category theorist to use monads in Haskell.
I find that demonstrably false. Every time I run into problems and ask for help, the answer is "there is this other mathematical concept that solves that problem".
It's not just monads, it's comonads, monad transformers, GADTs, Functors, phantom types, arrows, arrow transformers, the list keeps going. In addition, they're only described in terms of other mathematical terms - the same problem that plagues monads: nomenclature.
And these aren't just 'things you can use', if you want to understand the libraries you're using, you need to be able to keep up with all of those and more.
It's not like lisp, where you can mostly rearrange cons cells to make nearly any data type you like - there's no way to bootstrap your brain into understanding arrows from a standing start, at least in my experience as an autodidact trying to learn.
There's also Chris Allen's guide: https://github.com/bitemyapp/learnhaskell . You can also go through the (good, but very dated) book, Real World Haskell.
Sometimes you have to find the tutorials and blog posts first. The lens type signatures aren't the easiest to understand, and sometimes its easier to just use things "empirically" without fully understanding them, and then get a sense of the type signatures when you really want to know what the compiler's actually doing. Being able to use lenses is not as hard as understanding why its intimidating rank-2 type signature is the right one.
Finally, sometimes it helps to de-generalize. To replace (Monad m) with IO, for example, and think about what that special case might mean.
For example, the type signature for Control.Arrow.first is:
first :: Arrow a => a b c -> a (b, d) (c, d)
If you're a beginning Haskeller, your reaction is going to be "WTF"? Well "Arrow" is a type class more general than function. (It could be the "effectful function" type or Kleisli arrow, a -> IO b.) If you specialize with a = (->), you get the more concrete type signature: first :: (b -> c) -> (b, d) -> (c, d)
... and it's much more clear what it does.As for nomenclature, I don't disagree. I had this discussion with Brian Hurt (and owe him for the insights): we'd be more marketable if we called Monoid "Appendable" and Functor "Mappable". Monad is one where it's hard to come up with a more accessible name for it: it abstracts over computational context (i.e. what do we actually mean when we talk about computational effects) but that would be a mouthful of words and not any more clear.