Why I think Haskell is the best general purpose language as of June 22 2019
philipzucker.com
philipzucker.com
But perhaps Haskell is fundamentally ill suited to applications. I hope not. Other possibilities: A language's success may be more sociological than technical, Business factors dominate, success is totally random, who got there first, holdover opinions from eras of more constrained computational resources.
More answers for the same question: https://news.ycombinator.com/item?id=11907839
It doesn’t matter.
What matters is who talks the language, what is written in the language, where can you be understood in the language.
In programming language terms, the important questions are: do I have a library for X? Is bug Y solved quickly? How many answers do I have in stack overflow? Do I get job interviews due to that word in linkedin? Can I pair with a random valley programmer to work a quick pilot over a weekend?
When making a decision, using popularity as an easy but noisy indicator for quality can still make sense. If you kept your choice secret, you wouldn't even cause any negative externalities. But here, we don't make a decision so I don't think popularity is an argument worth considering (when evaluating the merits of the language itself, popularity does affect ease of hiring of course).
Granted, I don't know a great deal about that work directly, but I often hear about use cases for Haskell programming.
I suppose this is my bias - the only community I care about is the engineering side as supposed to my academic side.
Also look at ReasonML (and bucklescript). I have tinkered with it for Web front end and been very impressed.
As well as #ocaml on freenode and r/ocaml on reddit.
Yes, I also feel that Haskell has a larger community among academia/bloggers, but much lesser community among actual industrial users.
There are dozens of professional high quality OCaml software used by industry: Facebook's linters, Xen stack, Coq, Frama-C, Boeing's static analizer, FFTW, libguestfs by RedHat, camlpdf, Liquid Soap etc.
With Haskell, it feels like there are significantly less industrial grade projects written in it.
For what you say to have truly any validity you must use Haskell and an untyped functional language.
Some simple examples are when and unless, which work like if...then and if not... then.
In most languages, these would be control flow statements built into the language (or not) and could not be written by the user. In Lisp you could implement these with macros, with all of the caveats that apply. In Haskell they're just ordinary functions with all of the benefits of being first class values at runtime.
Why even consider that? Macros are IMO the main reason to use a LISP. As you suggested, they allow you to model laziness, or whatever else you might desire.
Macros are IMO the main reason to use a LISP.
It's funny that you say that. I've heard it before and it sounds great but from the time I spent in the Clojure community, people would always say "the first rule of macros is that you do not write macros!"
Laziness: You can build infinite data in Lisp but again, it's not as convenient.
Monads: Possibly the most mind-bogglingly useful programming pattern I've explored in the last 20 years, and you can't completely build them in Lisp. You can get about 75% of the way toward monads in Lisp but that last 25% requires manual one-off coding because Lisp functions don't automatically know the types they return. Even using macros I haven't figured out a way to solve this problem.
I don't see how any of Haskell's crazy syntax would make my life easier compared to node.js
By "combinator" do you mean combinator as in the combinator pattern?
I have no idea what value your comment brings us except a way for people who already agree with you to give you upvotes, and what's the point in that?
This drive-by-question style makes it hard for me to know what your real point is. Are you saying that an assignment does the same thing as a monad? OK. That it is a monad? I doubt it; assignment doesn't have the right operators (you might argue that it does, but you'd have to really stretch it.) That it's just as simple and easy to understand as a monad? I call BS.
> I have no idea what value your comment brings us except a way for people who already agree with you to give you upvotes, and what's the point in that?
That kind of rhetoric is against the site guidelines.
Using (something similar to) a monad (Javascript promises do not form a monad) successfully is different than using the monad abstraction successfully.
> and they are huge fans of do-notation in the from of async/await.
Async / await is not monadic do-notation. Arguably, it has a somewhat similar relationship to the underlying promise abstraction that do-notation had to the monad abstraction, but they aren't the same thing.
> Imperative programmers do not seem to have an issue with the idea of assignment, why are monads problematic
Why are the two halves of this sentence connected to each other since they have no relationship other than the proximity they've been (bizarrely) placed in.
function bindPromise(p, f) { return p.then(f); } function returnPromise(a) { return new Promise.resolve(a); }
Proof of the laws left as an exercise to the reader :).
But yes, you are correct that promises do quite a bit more than only being a monad, for example because of how they treat errors.
EDIT: I concede, I am wrong! https://buzzdecafe.github.io/2018/04/10/no-promises-are-not-...
I also think there's nothing precluding some Monads to be good ideas and others to be bad ideas.
Similarly, the delivery could have a big impact. So it might be the theory of it is good, but a better delivery in terms of programming UX needs to be used. So maybe the dot notation somehow delivers better then the do notation.
Having said all that, I like Haskell, better than JS.
return x; return x -> return yield*x
return yield x; yield x -> yield*x
(at least, I think it is; I may have made a mistake)That said, I think there are some legitimate reasons for the impression.
For one, Haskell (not uniquely) lacks the distinction between statement and expression found in many languages. This means that you have a freer hand about "where you cut" when breaking up your problem. In a way this is good - the optimal choice may be better when you have more options. But it also means a lack of consistency and more to learn about how to do it well.
Haskell's syntax is unusual. Everything is a harder to follow when you still need to work to parse things. There is a frustrating space between knowing the syntax well enough to want to learn other things and being sufficiently fluent that the new concepts are the only hard thing.
There are habits to reading Haskell code that differ from those involved in reading other languages - a big one being knowing how the types flow through an expression and how to spot where they're pinned down in various contexts.
And there's nothing wrong with wanting purity and immutability that badly. And there's nothing wrong with not.
I suspect that FP fits the way some people think, and imperative fits how some other people think. And I don't think there's anything wrong with that. I'm a fan of picking the tool that is best suited to the job, and the person who is going to be using the tool is one of the biggest components of "suited". I might even say, of all the languages that suit you, pick the one that best suits the task.
Their use is (seems?) straightforward - I have a context that can hand me a value, take values from me, or thread a state.
Also, they're "just" thin wrappers around common types. `Reader r` is `r -> a`; `Writer w` is `(a, w)`; `State s` is `s -> (a, s)`.
I'm interested whether you can unpack a bit where the difficulty seems to lie. Backgrounds differ and what's simple for one may be complex for another, without any judgement around overall capability.
And, here’s his first reason for liking Haskell:
> The number one reason is that there is something ephemeral that I just like. I am not naturally inclined to analyze such things. When I like a movie or don’t like it, it just happens, and if forced to explain why, I’ll bullshit.
When you started out refactoring and making changes to object-oriented programs, how much did you have to rip out and alter each time?
How did that skill improve as your designs became more thoughtful, as you began to see the seams and tailor your designs to fit those seams?
I believe the same would apply for Haskell: its seams are different, but the separated concerns that come from experience and intuition should allow you to follow those seams more closely.
One of the things I've come to appreciate about idiomatic Haskell is the library pattern (for lack of a better term). A properly designed Haskell project should be a library, not a monolithic program, and the problem you're trying to solve becomes a one-liner after importing your new library. A great example of this is Xmonad, which works exactly in that way.
I'm no longer confident that Haskell is the "best" language anymore. I was recently introduced to a language that might be even better than Haskell: Dyalog APL. (https://www.dyalog.com/). Try it out yourself (https://tryapl.org/)
To explain why, I recommend watching Aaron Hsu's videos on Dyalog APL:
- Does APL need a Type System? (https://www.youtube.com/watch?v=z8MVKianh54) - This is actually a very interesting question that is more nuanced than upon first glance.
- Design Patterns and Anti-Patterns in APL (https://www.youtube.com/watch?v=v7Mt0GYHU9A) - The main takeaway from this video for me was the principle of "Idioms over libraries."
- Higher Performance Tree-Wrangling, the APL way (https://www.youtube.com/watch?v=hzPd3umu78g) - Or how to model Trees without using pointers by using "Inverted Tables." (An inverted table is a table where the columns are the rows and the rows are the columns)
I can't avoid the comparison in my mind that Haskell is like Latin, spoken by priests, a very nice language Latin is.
Cry wolf too often ot be an assh*le too often, and expect this....
I enjoy Haskell a lot, but trying to create a CMS, desktop GUI or a console game in Haskell? Good luck with the existing tooling and libraries.
Even the languages that target the JVM or CLR are not supported on the existing GUI tooling, forcing you to do workarounds.
So Scala, Clojure, F# can do it, but you end up having to save JavaFX or WPF layouts, while throwing away the generated code, and load them via library calls.
Or you write the UI layer in Java/C#/VB.NET/C++, while writing the rest as a library.
So at the end of the day you are forced to chose between RAD productivity or FP purity.
EDIT: I have naturally forgot Common Lisp, but for that you should make use of Allegro or LispWorks, not Emacs + FOSS Lisp compiler.
But I can’t understand why record syntax is 1) completely necessary to write manageable type systems and also 2) known to be half-baked.
I also wish the community was better at embracing newcomers and teaching them one step at a time.
Other than that, I have no complaints.
Evidently, being in love with a programming language is an obstacle to comparing it honestly.
And moreover, please write a blog post or even short comment about it, because few Haskell footguns are obvious to me and I would appreciate the warning!
It is very easy to get over eager and use more abstraction than you need or can handle. This is perhaps the worst of them.
Strings shouldn't be [Char]. OverloadedStrings should be the default.
There are partial functions in base. head for example
It is easy to spring space leaks due to laziness.
Relatedly, choosing between foldr foldl foldl'
Incomplete pattern matching (which will be a warning) or sometimes default _ casing. If you add to the type, the compiler won't save you.
It is not necessarily so obvious to a beginner when you are doing tail call recursion.
Maybe overuse of typeclasses when records work better?
Over use of Template Haskell can raise an eyebrow.
A minority of extensions are ill advised.
All in all, I think the level of footguns in Haskell is in a different universe than C++, but I am trying to see it from the other perspective.
http://dev.stephendiehl.com/hask/#what-to-avoid http://dev.stephendiehl.com/hask/#the-dangerous
However, I was more asking for HelloNurse's opinion, since I can't think of any Python footguns that are on the same level as C++'s. The ones you cite are more on the level of Python's.
It explains organized footgun management, with a discussion of what language extension should and should not be enabled, and some specific library threats (e.g. String and ByteString).
Haskell programming at its best starts to feel like you're putting together a jigsaw puzzle, and everything "just works" once you get it to compile.
Honestly, it's hard for me to take seriously any post/comment including this.
How portable is Haskell? Does it have a wide range of graphics/sound/UI libraries available? Are those libraries available on a large number of the platforms that Haskell runs on?
This are the kind of questions that many C/C++ programmers considering alternatives might ask when considering whether other languages are general purpose enough for their needs.