This is one of the best essays addressed to programmers I've ever read. It speaks to you on a very personal level. Highlights:
> Haskell wasn’t built on great ideas, although it has those. It was built on a culture of how ideas are treated.
> In functional programming, our proofs are not by contradiction, but by construction. If you want to teach functional programming, or preach functional programming, or just to even have productive discussions as we all build libraries and projects together, it will serve you well to learn that ethic.
> Believe in everyone, attack nobody, even the trolliest.
> If you make even the most modest (to your mind) mistake, be it in social interaction or technical detail, be quick to apologize and retract, and do so freely. What is there to lose? Only your pride. Who keeps track? Only you. What is there to gain? Integrity
> Your self-esteem doesn’t need your help. You may feel you need to prove yourself, but you don't. Other people, in general, have better things to do with their time than judge you, even when you may sometimes feel otherwise.
> Be glad that others are charting other paths! Who knows what they will bring back from those explorations.
> Every time we learn something new and want to share it, we face these issues all over again -- the desire to proclaim, to overturn received wisdom all at once -- and the worse the received wisdom, the more vehemently we want to strike out. But if we are generous listeners and attentive teachers, we not only teach better and spread more knowledge, but also learn more, and enjoy ourselves more in the process.
This is my favorite section of the essay as well. What a great approach to disagreement, and how fruitful!
It's a mindset that shows tremendous respect for others, yet tremendous self-assurance. It's the faith that the best ideas will win out in the long run.
> Now, you’re a social person, and you want to go forth and share all the great things you’ve learned. And you have learned enough to distinguish some true statements from some false statements, and you want to go and slay all the false statements in the world.
I learned some Haskell recently and I'm somewhat enthusiastic about it. It's a very difficult language, I took a lot of effort to learn Haskell compared to most other languages. It's still difficult to understand other libraries and code. But personally, For me, it was worth the effort to learn and understand it.
I don't think it's worth the effort for everybody. I don't think it's fun for everybody. I don't think it's the best tool for everything. I have no desire to spread the good word.
If you start from the premise that it's the best language out there, everybody should learn it and that it is easy, you'll get into trouble.
Edit: I don't get the downvotes -- maybe I did not express myself clearly?
I was going to downvote you but didn't, seems like you got a fair share of those already.
My reason for downvoting you was that it seems you didn't understand that this essay is a "Letter to a Young Haskell Enthusiast", it's not for everybody, it's for a young haskell enthusiast, that's the point.
Your comment seems to have no place if you think about the kind of people that essay is aimed for.
When you say "I don't think it's worth the effort for everybody", that's exclusionary, and totally counter the tone of the article, so I don't think your comment belongs in the thread about this article.
So the negation would be "Learning Haskell is worth the effort for everybody". I think it is arrogant to say that when there are thousands of skills to learn and a limited amount of time.
That is not what "I don't think it's worth the effort for everybody" means. Some people have a greater return on investment improving their skills for a language they already know, learning a language that is not Haskell, or learning a skill that is unrelated to programming.
This is an incredibly strange series of comments. OP simply stated that in his assessment from his use of the language (and the time it took him to learn it), that it isn't for everyone, and thus HE won't be spreading it. Notice he doesn't speak about preventing other people from spreading it or anything of the like, he's simply making a personal decision of what he will evangelize.
You have to be in a uniquely defensive mindset to cast this reasoning, a reasoning we ALL have to do eventually given limited time, as "arrogant". I personally think learning assembly is not worth most people's time. If I were to teach a web programming class I might choose to skip assembly. Can I be sure that people wouldn't get something out of it? Of course not. Is it "arrogant" of me to assume that people will find it hard and it is not the best use of their time, no, thats ridiculous. There are more topics than time, so its fine for me to choose what I believe is most helpful to other people to preach about.
Thanks for taking the time to formalize your thoughts in such a clear and elegant manner.
Everyone needs a periodic reminder to keep their ego in check. On the one hand it drives ambition, spurs achievement, and encourages personal development. There is almost unlimited power in the concept of self.
Me against the world. My achievements.
I think this attitude is very prevalent in programming and the tech world in general. It is manifested and reinforced by the wild popularity of startups (My idea is good and I can go it alone) and the tech visionaries (Gates, Jobs, Musk) who seem to carry the weight of the world on their shoulders.
On the other, overfeeding your ego will make you narcissistic, selfish, insecure, and hostile. You will lose your empathy for others, and ultimately, your humanity, as you start to lose sight of the big picture: progress is a process that started long before your time and that will continue unimpeded to infinity, even after your infinitesimally tiny ego is wiped from existence.
As Isaac Newston put it best: "If I have seen further it is by standing on the shoulders of giants."
I agree very much with your sentiment, but that quote by Newton is actually far more mean-spirited than you think. It was Newton making a huge burn about Hooke, one of his main scientific rivals, who was actually very very short.
Newton was possibly the greatest intellect that humanity ever produced, but he was not a nice person.
I'll go against the grain and say that it's a pretty dangerous article.
What it wants you to do, slay false statements and spread what you know, is exactly the kind of thing that goes terribly the minute you fail to figure out what is true and what is false. Very few things in computing are really black and white, but spending our time proselytizing just leads to more thinking in a black and white world, and adoption of technologies that might leads us in the completely wrong direction (Hello Spring!)
What we have to tell a young language enthusiast is that there is much insight in ideas different than our own, and that there is much to learn in looking outside of what you consider the best. Maybe there are tools that are better suited for other kinds of problems. Maybe not everyone that disagrees with you is very wrong about things and needs to be converted.
I mean, how can you even try to ask people to improve their communication skills, when you say that people that do not think programming is math is because they have the wrong notion of math?! I just don't see how you are going to convince anyone of anything with that level of condescension.
Frankly, and being a bit meaner than I should, it seems to me that the reason Haskell can't catch on is precisely that enough of its community thinks like this.
(Disclaimer: Haskell fan who is also a complete newbie here).
I like what the article is trying to do, but I must admit there is something off about it. Maybe it's me, but I read between the lines something like "you and me both know Haskell is the best language, but try to be gentle with unbelievers and admit that nobody, even Haskell programmers, is perfect. Other languages have some good insights, too." which sounds a bit cultish to me, a bit like teaching a Jedi knight to be humble. A truly open-minded position would have to continually consider that maybe Haskell and its type system are not the best options at all, instead of merely adopting a humble attitude and avoiding aggressive confrontation.
Nothing wrong with believing a tool is better than others (I do!) but it makes the article sound a bit condescending...
I'm ready to admit maybe I'm wrong and there is no implied presuposition that Haskell is superior in the article :)
----
Re-reading other comments, here is something related to what I've just said. Someone quoted Newton: "If I have seen further it is by standing on the shoulders of giants."
That statement sounds humble (a "humblebrag", some other commenter called it) but carries the implication that you have, indeed, seen further. Maybe the assumption that you as a Haskeller have "seen further" sounds immediately condescending to others who think differently.
> A truly open-minded position would have to continually consider that maybe Haskell and its type system are not the best options at all
There are two ways that I can parse this comment. The first is that you mean that there are other, newer options out there that will turn out to be better than Haskell. This, almost all Haskellers would agree with: most of us have more than a passing interest in e.g. Idris, Agda, Shen, etc.
The other reading is that you mean that other established paradigms are better options (A third reading is that there is no such thing as better, but for that I'll just point you to pg's classic Blub essay). This is a good thing to consider once, but I strongly disagree with considering it continually. Once you've made the comparison, if you come to the conclusion that one tool is better than another, it doesn't make sense to continue that comparison forever. It may make sense to revisit it from time to time as you grow in your understanding of the task and the context, but at some point your posterior probability of the other tool being better must grow so low as to no longer be worth investigation. For many Haskellers, the comparison between a Haskell-like type system and dynamic typing is this kind of comparison. My posterior probability of dynamic typing being a better choice is less than one percent, so it makes no sense for me to continue reevaluating that option.
If the latter is what you mean, I can't disagree that it is a truly open-minded position, I can only point you to a quote by the inimitable Tim Minchin: "If you open your mind too much, your brain will fall out."
For a given problem, no doubt, some languages are better than others. I still doubt one can say that in general, without qualifying what kind of problem he's solving.
I'm just writting a device controller in a side project (at userland - I already have enough problems to solve - the kernel sees it as a soundboard and a USB TTY). At fist I tought "wait, great time to try some serious reactive programming in Haskell", but I gave up, C++ looks much better fit to that problem. When it's done, I'll probably write some Haskell wrapper, and use it in a functional reactive program, but Haskell is just not the language for the controller itself.
Also, another side project requires a CRUD web app, with some simple rules. It's in Python. No way I'm going to write it in Haskell. Another component is a TCP server with a complex behaviour and that I want to scale, it's in Haskell, no way I'm going to write it in Python. Another component is in VB.Net, go figure...
Maybe there is a young and mostly unkown language that is indeed best - no strings attached. But it's certainly not Haskell and I still didn't find it.
There's definitely a tradeoff between library maturity and language quality. There are also a few specific domains that are best-served by more domain-targeted languages. That doesn't mean we can't say that, aside from those issues, one language is better than another. I can say that Haskell is a better language than Python and then go ahead and use Python anyway because NumPy/SciPy/pandas or whatever. We can separate the issues and render judgments about language quality independent from library maturity, etc.
The existence of specialized domains justifies an argument that you should use specialized languages in those domains, but that is almost never what we're discussing. Java, Python, Ruby, Haskell, Clojure... none of these are languages specialized for a given domain. They're all general-purpose languages, and if you compare them as such independent from their libraries, Haskell is the best of them. That does not mean that it's the best choice for every project, but that's a completely different question.
It's the flexibility of Python that makes it great for writting CRUD applications with diverse data types, at the same time that it's the rigidity of Haskell that makes it great for writting a complex specialized server. It's the unsafety of C++ that makes it great for directly interfacing devices, but you really does not want that unsafety in any of the other examples.
None of that is a matter of maturity, it's the other way around, the available libraries are good for different tasks because the languages allow them to be. You can't just compare those languages without context.
I wasn't going to wade into the object-level CRUD app discussion because it seems beside the point, but I can't possibly disagree more about Python somehow being better suited for the domain because of "flexibility". Python is not more flexible than Haskell in any meaningful way.
The only possible argument against static typing comes in the form of a program that won't typecheck, but should. This is the only type of "flexibility" that Python could win at, with regard to type systems. Please, show me a practical example of such a program. I've asked a dozen people for one, and nobody has ever followed through.
The only other argument against Haskell's "flexibility" I can think of would be against purity, but that argument doesn't fly either. Any competent Haskell programmer can work easily with state, IO, etc, and I've never run into an effectful task in practice that takes meaningfully longer to do in Haskell than in Python.
People are often quick to typecast languages into some role that seems to fit. Haskell is rigid and mathematical, Python is flexible and readable, etc. These impressions rarely come close to capturing the reality, and in this case end up being downright misleading.
If I'm starting developing a web application from scratch, with zero libraries available to me, I'm picking Haskell without a shadow of a doubt.
Every single value in Python is weakly defined, and can change at runtime. Functions can accept any set of parameters, objects do not need to conform to a class, the entire namespace can be replaced during the execution of a function. If you have a better name than "flexibility", please tell me, because I can't think of any.
Haskell is in the oposite extreme of that dimension.
Anyway, that has no relation to readability. Python's flexibility leads too easily to metaprogramming, for example, what's extremely powerfull, but a nightmare to read. And classifying a language as "mathematical" is borderline nonsensical - it only carries some slight meaning because people that say that normaly want to say "algebrical", in oposition to, maybe, "logic-temporal".
Maybe reread my post - I wasn't saying that those typecasts of the languages were accurate, I was doing exactly the opposite.
The characteristics of Python you just mentioned are only specific to it in cases when they are erroneous. They basically all evaluate to "Python isn't type-safe." So again, show me a program that is best represented in a non-type-safe way, and I will concede the point. If you can't, then this flexibility you're praising isn't a feature, it's a bug.
> The characteristics of Python you just mentioned are only specific to it in cases when they are erroneous.
They are explicit at the official documentation, if they got there by error, they are official features now.
> They basically all evaluate to "Python isn't type-safe."
Yes, they do. They are at the opposite extreme from type-safety. That's why I used them to exemplify how it's the languages that apply better to some problems.
> So again, show me a program that is best represented in a non-type-safe way, and I will concede the point.
Well, any Django[1] CRUD would do. They are quite trivial, in there's little meaning in specifying exactly the manipulated data. Yes, Haskell has tools for displaying data at the web, and querying a database; no they are simply not as powerful when applied to that problem.
[1] In other frameworks they are about as simple, but you asked for one example.
I find this a strange and unconvincing example -- if I'm understanding you correctly, that is. Is your complaint about strong typing here that you'd be forced to define stuff like a record Customer with fields "lastName", "firstName", etc. and you'd rather avoid that?
If you'd like something more "dynamic" (i.e. type-unsafe), you can instead just define a "universal data type" for all your CRUD data. For example you could define, say
data Any = Number Int
| Str String
| Map String Any
| Date ...
| ...
and where you want "universal" data manipulation you just use Any.
EDIT: Thus you've confined all the "fuzziness" of your data definitions to a "subsystem" of your system and you can still benefit from proper types and type checking everywhere else.
Where do you find that Python is better than Haskell for CRUD applications? I've found the type system to eliminate most common CRUD application/web dev bugs and make me much more productive.
You presume that reevaluation of your position is an expensive operation that we must economise on. But sometimes it is just keeping your eyes open. For this particular question, I see lots of very good and beautiful written in imperative and dynamically-typed languages. There are many problems for which the most natural program is imperative or object-oriented. So to me at least looking at the programming language world with the presumption that Haskell-like languages are always superior seems cultish indeed.
It's not a presumption. It's not a prior that we're holding to regardless of evidence. The superiority of Haskell is, for all the Haskellers I know, a conclusion that they came to after extensive research and experimentation. It's not like we were somehow trained in some hidden refuge where imperative and object-oriented languages aren't spoken of. I cut my teeth on PHP, of all things. I know what's out there, I've made the comparisons, and I see no reason that I should keep doing so forever.
When you say "problem" you are describing something higher level than just an algorithm, yes? Could you give some examples of problems that the most natural program is imperative or object-oriented?
I mean the latter, but not because it's my position (I certainly don't think an effective use of my time would be to continually re-evaluate each of my opinions on programming languages), but because I think it would mesh better with the article's tone of "humility above all things".
My own opinion is that sometimes you're right and your interlocutor is wrong, and sometimes this means you simply cannot avoid sounding condescending.
You point us to the Blub essay as if that settles the matter. It doesn't. I think the Blub essay is wrong.
Here's the Lisp people. They're sure that they are at the top of the power curve (including compared to Haskell), and they can tell you exactly why. "How can you get anything done in Haskell? It doesn't even have macros."
Over here are the Haskell types (pun intended). They're sure that they are at the top of the power curve (including compared to Lisp), and they can tell you exactly why. "How can you get anything done in Lisp? It doesn't even have a decent type system."
This situation - two different languages each looking down at the other - reveals the problem in pg's Blub Paradox. The problem is this: The idea that all languages can be ranked on a one-dimensional axis called "power" is wrong.
You can see this with hardware, for instance. We know what power is in hardware - it's MIPS. But once you think a bit deeper, you might remember that your workload contains a fair amount of floating point, so you have to worry about FLOPS... and there's that one data set that doesn't fit into cache, so you have to worry about memory bandwidth... or would it be worth lower MIPS to have a bigger cache? Now "power" has at least four dimensions (MIPS, FLOPS, memory bandwidth, and cache size). Even more (but for the same reasons), it's naive to say that programming languages can be strictly ordered according to on a one-dimensional "power" axis.
So now you have to start asking "power for what"? I think this is the right question, because nobody ever writes a general computer program. We always write specific ones. We want a programming language that has the most power for that specific problem we're trying to solve.
Once you crack open that door, in walks (for example) a Fortran person, who asks, "How can you get anything done in Haskell or Lisp? They don't even have decent matrix packages!" And before you say "of course they can do matrix math", by "decent" the Fortran person meant a package that can, for example, efficiently handle a banded hermitian matrix with complex elements, and still get good answers even if it turns out to be a stiff problem. I strongly suspect that Lisp and Haskell matrix packages aren't yet up to that standard. (And if you're going to say, "Well, that's just a niche", I suspect that niche is at least as big as the entire Haskell universe.)
Then a hard-real-time embedded programmer comes through the door, and says that their world needs a language that not only doesn't garbage collect, but doesn't cons either. (That niche is probably also as big as the Haskell or Lisp universe.)
And so on.
Think of programming languages as a tree. Think of your problem as a vector. Use whatever branch of the tree gets you the furthest along the vector of your problem. In other words, the best tool for the job. It's not always Haskell. It's not always anything. Learn more than one tool.
Your point that there is more than one axis on which to measure the power of a programming language is well-taken. That said, you can normalize to one axis. The point of pg's essay is that only people who have learned the relevant tools are qualified to judge them.
The solution to your Lisp v. Haskell dilemma is simple: ask the people who know both. I agree with Lispers that macros are powerful, and the stuff in the book Let Over Lambda is ridiculous and awesome. I also think that macros are dangerous, and I prefer to only use them if there's no other alternative. I pick Haskell over Lisp, having used them both extensively, and I've seen far more people come to Haskell from Clojure than the other way around.
With regard to Fortran, embedded, etc, see my response to marcosdumay. Yes, those niches are sizeable and you should use the correct tool for the job. That has no bearing, though, on the question of which programming language is better.
True, but such a normalization is not unique. That is, one language or the other can come out as "more powerful", depending on the normalization chosen.
Your point about "ask those who use both" is harder to refute...
> I mean, how can you even try to ask people to improve their communication skills, when you say that people that do not think programming is math is because they have the wrong notion of math?! I just don't see how you are going to convince anyone of anything with that level of condescension.
You're projecting a level of condescension onto Gershom's words that just isn't there and makes no sense within the context of the article. His point is that the "debate" about programming/mathematics is largely one of semantics and consists of well-intentioned people arguing from a different set of definitions. I'd hardly consider this to be a controversial statement, much less condescending.
Did you read the same article I read? The article states the exact opposite of what you said, that you shouldn't go around with the goal of "slaying dragons" (slaying what you think are falsehoods)
... Are you sure your clearly preconceived notion about "Haskell People" didn't taint your perception?
"Every time we learn something new and want to share it, we face these issues all over again -- the desire to proclaim, to overturn received wisdom all at once -- and the worse the received wisdom, the more vehemently we want to strike out. But if we are generous listeners and attentive teachers, we not only teach better and spread more knowledge, but also learn more, and enjoy ourselves more in the process."
"What we have to tell a young language enthusiast is that there is much insight in ideas different than our own, and that there is much to learn in looking outside of what you consider the best. Maybe there are tools that are better suited for other kinds of problems. Maybe not everyone that disagrees with you is very wrong about things and needs to be converted."
The article says exactly the opposite, but you're too lazy to read.
It's a shame this is titled to target Haskell developers - it feels like it would be a good read for most young developers.
(though I can see how the endless feature-incorporating (typeclass-based) refactor cycle is particularly relevant to Haskell - come to think of it, I think many somewhat older Haskell developers could stand to take from this too)
You're right - this letter fits perfectly with many languages.
Letter to a Young Visual Basic 6 Programmer
[...]
So how do you help them want to learn it too? You do not tell them this is a language for smart people. You do not tell them you are smart because you use this language.
"You do not tell them this is a language for smart people. You do not tell them you are smart because you use this language. You tell them that types are for fallible people, like we all are. They help us reason and catch our mistakes, because while software has grown more complex, we’re still stuck with the same old brains. If they tell you they don’t need types to catch errors, tell them that they must be much smarter than you, because you sure do."
This tactic is used a lot in evangelism talks and it doesn't work. A lot of the non-FP people listen to these talks and come away thinking, "this person is obviously really smart", and then it comes up in the discussion afterwords, so not only is it unhelpful, but it distracts from the message and perpetuates exactly the myth that we're trying to dispel. We have to calibrate to the audience's understanding of relative words like "smart".
I tried to say something like this in another comment. I am a Haskell fan, but the article sounds like evangelism -- and like with evangelism, its tactics of always-show-you're-humble will inevitably annoy a large number of people.
Yes, yes, being rude also annoys people. What I'm saying is that many people detect the evangelist's "always humble" attitude for what it truly is: hidden condescension.
I didn't read the article that way at all. I read it as a plea for real humility, not fake humility. And I don't think real humility can be hidden condescension.
The article addresses a real problem. Haskell is presented by its neophytes as some uber-arcane thing that cannot be understood by a mere average programmer, you have to learn algebra first!, and read all Martin-Lof, and whatever else. And it hampers adoption of the language by many other people who might be offended by such superiority attitudes.
However, it is much healthier to present Haskell as simply a tool for writing better and safer code, which is frequently easier to reason about than your conventional for-loops all the way down. So everyone should try it, and say for themselves.
I may be wrong and over-generalizing here, but Haskell is a very convenient vehicle for showing off and belittling others. And honestly, who does not want to stick Haskell somewhere in their CV just to look better nowdays? Being fancy has a cost for the language. This is not an intrinsic fault of Haskell. People just need such a thing. If there were no Haskell, we would have APL, Lisp, Erlang, C++, or something like this.
But isn't it also a mistake trying to portray Haskell as just-another-langauge? It clearly is not, it is more difficult to learn. Like with most things in life, the benefits appear after putting a lot of effort into it. I don't get the impulse to portray Haskell as "easy". The perceived arrogance of Haskellers may also come from that.
You don't defuse arrogance by saying "Look, I'm not smarter than you. This is easy. Now let's talk about Monads, they're just like Tacos. I'm patient."
Better be honest and say "Look, I'm not smarter than you. This is hard. We need to start with data types, and the benefits won't be obvious until long down the road."
I think it is anything but clear that Haskell is harder. What may be clear is that functional languages are harder to learn for people who have already learned imperative programming. But then you're forgetting the massive time investments they already made in that style.
Having TAed intro classes at a university, I can say from experience that new students pick up functional style much quicker and are always confused by mutation until they've had a fair amount of experience with it.
Haskell goes way beyond just functional programming. Most of the interesting stuff is happening in the types: monads, applicatives, lenses, etc. And when you're trying to understand something like:
This I disagree with. Telling someone that something is hard before you teach it to them is a self-fulfilling prophesy.
My wife is a native Russian speaker, and she is slowly teaching me Russian. I struggle when learning new languages, so it's easy for me to get discouraged when the progress seems too slow.
My wife often teaches me a few words at a time, and without fail, when she says, "This word is hard," before teaching it to me, it takes me the longest to learn those words.[0] It's like my brain, upon hearing that something is going to be hard, assumes that I'll forget it anyway, and simply turns off.[1]
If you are getting ready to teach a difficult topic, perhaps spend a little more time beforehand trying to find good analogies and approaches. Oftentimes, a topic's difficulty melts away when a student can make an appropriate connection.
Don't confuse the difficulty of teaching a topic with the difficulty of learning it.
[0] You might argue, "Those words probably are harder." That's a fair point, but in the hours before our wedding, I managed to learn how to say, "Я знаю что я никогда не буду голодным. [I know that I will never be hungry.]" On the other hand, it took me days to learn, "карандаш [pencil]" after she told me it was a hard word.
[1] When I recognized this phenomenon I asked her to please stop telling when she expects something to be hard.
It is important to set realistic expectations. The popularity of different programming languages is note purely random or an historical artifact. Some languages are easier to learn than others. If a student struggles to grasp an "easy" concept, she might give up prematurely.
I've witnessed this a lecture: the Professor tries to sell Haskell with the dreaded quicksort one-liner. In my opinion, that's the classic show-off example where it's easy for somebody who knows Haskell but hard for somebody who doesn't. Most of the class thought "obviously this is beyond my capabilities" and tuned out.
Of course, students should also know that hard problems are overcome by effort, not intelligence. I know the effect you're talking about, but it is a good habit to consciously not try be discouraged by hard problems.
> But isn't it also a mistake trying to portray Haskell as just-another-langauge? It clearly is not, it is more difficult to learn.
I don't think it is. I think (as is the case with functional languages and languages with non-Algol-inspired syntax generally, and Haskell falls in both groups) Haskell is harder to learn as an N+1 language than an imperative language with Algol-inspired syntax if you are a programmer whose existing familiar is with N languages that are all imperative languages with Algol-inspired syntax, for N > 0 (and this is increasingly true with increasing values of N.)
If you've got some background in functional languages without Algol-inspired syntax (e.g., Lisp) and some background in statically typed languages (even imperative, algol-inspired ones) it doesn't seem to be fundamentally that hard to learn, though.
I think that there is something of a deficiency in that there isn't a lot of good tutorial documentation (at least, that I've seen) for Haskell that is well designed either for new programmers or for experienced programmers without a background in things like category theory, but AFAICT that's not anything fundamental about the language, but more something about where it came from and who the early audience was. As Haskell seems to be getting broader attention, I expect that will improve.
Syntax differences very clearly are a source of difficulty for many people learning new languages, especially when there experience is focussed on a particular syntax style.
> the very sophisticated type system is.
I don't see any evidence that Haskell's type system makes it harder to learn from an absence of programming knowledge. Like its non-Algol syntax, it probably makes it harder for experienced programmers with habits centered around patterns learned in less expressive static type systems or un-/dynamically-typed languages.
If anything, I think the consistency of the type system and the relative lack of ceremony probably makes it easier, in some ways, than C/C++/Java family languages, where there is lots more type ceremony to learn.
Good point. Programming should be explained at the right pace, and in rather small digestible chunks. Then Haskell is not harder than anything else. The basics of Haskell are very easy actually. Function is just a function, it maps values and you can call it recursively. And then, advanced topics are hard in any big language, and in my opinion C++ is the queen here, yet it's taught to freshmen in some schools.
I'm not a Haskell developer but the main idea in this article is big enough that it can be applied to any situation where you feel that you know better.
Years pass and I always feel that I got rid of this "proving that I know better" motive but, every time I look back, I always see that I still acted with it and it was usually me who could do better. At the very least, I always feel that I could do better in the social area - like, communication.
It looks like I'm one of the few people on here not excited about Haskell. Functional programming is great. Static typing is nice, yes. Hindley-Milner type-inference even moreso, but I often find the language getting in my way. Now, I'm not a Haskell expert, but I have used OCaml for some fairly sophisticated problems in the past (basic optimizing compilers). So I'm curious for the people who have used Haskell for something substantial whether they've found their experiences match with mine.
This probably doesn't meet your (or my) qualification for substantial, but might be useful anecdata.
I recently used (early July 2014) Haskell for a crud app with a daemon that does some web scraping/form posting where no API existed for a freelance client.
Haskell did not get in my way whatsoever. Here are some general stats about the application:
604 loc (was 1400 at one point, 900 after de-duplication, 604 after refactoring)
112 commits
The crud website and daemon program take up about 200 MB of memory IIRC on a $5 per month digital ocean droplet.
Haskell is a research language. It is the most viable research language for production applications. A few people will solve a major business or life problem with Haskell. Many more people will take the ideas back to improve the quality of their Java or C# code.
I actually learned some Haskell during my CSC degree, and it was actually a language that I took to really easily and enjoyed. I actually went home and made sure I could write haskell programs at home. It's been 8 years now though and for the life of me I've never been able to think of something I'd use it for.
If you enjoy Haskell and programming, why not start a hobby project with it? It's a general purpose language after all.
(Using it at your day job is a different proposition, of course. I'm still having arguments with my boss over the use of Scala instead of Java. Imagine if I proposed moving outside the JVM!)
I have lots of hobby projects, I just can't see how Haskell itself would be useful. I do back-end stuff at work, so most of the stuff I do at home tends to be front end web apps. Based on what I learned of haskell at the time, it doesn't really seem like the right language for that sort of thing.
Nice attitude, that's for sure. However I feel like this is targeted at the open source community. At work, it sucks to be better, because I'll get the harder bugs, deeper work, more work, tough refactorings, architecture planning, and everything that programmers who can't even write decent PHP can't do.
I love getting that stuff. For me, the fun in work is to work on stuff that is hard and fix it and/or make it easy.
I will work on easy stuff when it is necessary and stuff just needs to get done, and I recognise that a lot of work is about getting easy stuff done because value is often tied to tedium not to complexity, but to me the fun part is when value comes from making sense of the stuff that doesnt make sense currently.
> At work, it sucks to be better, because I'll get the harder bugs, deeper work, more work, tough refactorings, architecture planning, and everything that programmers who can't even write decent PHP can't do.
At many workplaces, its awesome to be better, because -- while, yes, those kind of assignments come with it -- so does more advancement and security.
What sucks about being at the higher end of some teams is when other people come to you with trivial problems that they just can't be bothered to look into themselves. I'm happy to help people learn but I don't like being expected to do your job for you.
There is something called "decent PHP"? Use Haskell! =) (This joke is so relevant that I couldn't resist!)
Joking aside, my idea is that a job isn't good for one as long as you feel you aren't learning anything but rather covering for other people. Monetary compensation is not enough for these kind of situations because the programmers I know generally are motivated not just by money but equally from the sense of accomplishment as well. It's not about "confirming that you are smarter and know more" as discussed in the article but rather the very basic feeling of getting things done.
This is something every young dev should know, Especially if you're a regular full-time employee.
The job should do something for you! You may be paid well, but you must feel like you're getting something out of it too; and if you have any sort of intrinsic motivation you can't expect to be satisfied with just money. It may be on you to find out what that is, there's no guarantee it will be technical in nature.
There are times when this won't be the case, though, and you'll need to grind.
I get the impression that this essay is targeted quite specifically at elements of the Haskell community, and isn't just a general comment. I've not experienced it myself, but I've seen backscatter from people having thorny interactions with some Haskellers as they try to level up. The existence of #nothaskell would seem to support this.
It happens with humans in general, probably one of the cognitive fallacies. Whenever we gain new knowledge, we get infatuated with it and for the period of infatuation we block out everything else. It could be any kind of knowledge gain - "Hey I know the shortest path to office and I don't care what path you take or suggest, mine is the best one".
My message would be this: "It is amazing what we know or learned, but what is more amazing is the stuff we don't know yet - so be curious, not infatuated".
This is a great article and the ideas go way beyond Haskell and programming. We are all still learning and our interactions with people can be much better if we remember that.
In some sense, it also reminds me of the xkcd comic on learning new things http://xkcd.com/1053/
Wow, so many truths and core principles about life and social interaction in such a concise post. I have started 'fiddling' with Haskell recently but after reading this I realize I have some serious work to do with my interpersonal skills and communication and being more considerate to others.
Enlightening on all fronts..
> Remember also that they were put off by your actions, not by your existence
Some people can be put off by your name, like when their primary interest is their product is marketing its name rather than the technical merits of the product.
Hmm ... Pedagogically, I wonder if Haskell suffers from this emphasis on math.
For instance, I couldn't figure out State monad for the life of me, and in general how monadic calls could maintain a context "in the background". Explanations like "it's easy just follow the Kleisli arrows" weren't helping.
Finally I did the exercise of manually "inlining" every >>=, 'get' and 'modify' call in a trivial example of a StateT function calling another StateT function. And then I got it. Truckloads of closures/continuations, constant calls to re-create the monad with new information. Function calls with functions as arguments that close over the previous calling function's state.
A lot of this was specific to how StateT + Identity unwrapped; I'm sure inlining other monads would reveal different things, and unwrapping IO is impossible in GHC :). My point is, math has been a great source of Haskell's incredible expressivity, but the pedagogical focus on math threatens to mask it's greatest triumph in Haskell: making all of that boilerplate code go away with incredible precision and elegance. When you rip it open and see what >>= or 'do ... get ... modify' is doing, you feel the power.
I feel like the article suggests this, too:
The only thing you need category theory for is to take great categorical and mathematical concepts from the world and import them back to programming, and translate them along the way so that others don’t need to make the same journey you did.
At least for advanced programmers from other worlds, they need to see the guts to appreciate how amazing this stuff is.
Seeing lots of those monads unwrapped and the lambdas that they get turned into can be especially helpful for those of us (including me) that have an imperative/OOP background.
I think what followed this quote made quite a good job at explaining what exactly he meant with this statement: That people tend to have a limited view of math as calculus only.
One thing that I think is true (and maybe this is what Ono-Sendai meant) is that compared to many languages, Haskell's syntax is relatively close to the notation used by mathematicians. And notation can strongly influence the way we think about things.
I was introduced to programming before abstract algebra, and when I took my first algebra class the comparison to Haskell was inevitable. Actually it turned out to be quite helpful: strongly-typed functional programming can be a good supplement to learning algebra.
Haskell just clicked for me not long ago after 4 years of revisiting it periodically, writing one-liners and small programs, and reading tons of material on it. All the tutorials in the world weren't helping it click for me.
But then somehow I finally understood that Haskell is (trying its best to be) Math. I had a deeply mistaken idea of what math is and I thought I "hated" it and that any kind of advanced math is too hard for me. I have failed Calculus before, though I've always done well in discrete math.
It was only when I realized that math begins (or does it?) with what you have (objects, sheep, anything you want to count) and what you can do with them (group, make a set, join two sets, etc). Then I went into a reading spree about all ofthose very basic and foundational aspects of pure math (pure as in "look around you, you can count things, you can group them based on some trait, you can do operations based on groups, you can now think of those groups as the entities to focus on, you can prove certain properties about those groups, etc") and I found it amazing that so much can be known and discovered from starting with just what you see around you.
When I understood that math starts with just looking around you then I finally made peace with math, and I saw that it was good, that it was here to help me. Then I looked at Haskell again, and suddenly Void, Unit, Either, Maybe, they all made perfect sense. Maybe is a function that takes your set and gives you a new set that looks the same, but has a special entity that means "the lack of an entity in this set"; in other words, Maybe adds a zero to a type. It's simple and easy for me when I choose to see it that way. Everything is a lot more concrete and I have even drawn all these concepts and they map very well to visual ideas. So many things in Haskell are recurring themes (like adding a zero, starting things with a "one" entity, etc) that if you have a good relationship with math, many things fall into place just nicely.
But I started Haskell hating math and that has held me back so much. So my advice would be to never deny that Haskell is math, but to explain what's so awesome about math, how it gives us so much certainty even if we only assume very basic and seemingly obvious statements. I could have used some rough advice like "listen, stop whining about math, you're wrong about what you think math is, it's much more fundamental and it's a tool to help you organize any set of ideas you have, so why would you not apply that to programming?"
It was only when I realized that math begins (or does it?) with what you have (objects, sheep, anything you want to count) and what you can do with them (group, make a set, join two sets, etc). Then I went into a reading spree about all ofthose very basic and foundational aspects of pure math (pure as in "look around you, you can count things, you can group them based on some trait, you can do operations based on groups, you can now think of those groups as the entities to focus on, you can prove certain properties about those groups, etc") and I found it amazing that so much can be known and discovered from starting with just what you see around you.
In the early '70s, there was a global movement in math pedagogy that took this angle to elementary learning.
Instead of arithmetic, first graders were taught set theory. Elements and unions became the first mathematical concepts introduced to 6-year-olds.
In the US, I think they called it "New Math". Here in Finland, set theory was included in the national educational system's grand redesign. Regardless of country, set theory as elementary math seems to have gone out of fashion as quickly as it gained traction, and by the early '80s was out everywhere.
Maybe, if they had stuck with it, we would all be using Haskell now as a side effect :)
I took a History of Mathematics module as an undergrad and remember our lecturer telling us the main reason "New Math" never stuck was because parents were no longer able to help their kids with their homework.
On a very abstract level, I don't really think it makes a difference. If you start from one sub-domain as a primary foundation in mathematics, you eventually wind up realizing you can define that sub-domain easily, using different sub-domains of math. Realizing that is I think, where category theory sprang from. That last bit, I could be totally wrong on - I tried to teach myself category theory and wound up building webs using abstract algebra and formal logic.
That's obvious if you program, though (to me). What you can do in one language, you can do faster, slower, more concise, more verbose, more symbolic, more literal, and so on, in another. You can build constructions and you can break them apart, depending on what layer of abstraction you can get to. You can call it by it's specific name and functionality, in how the part interacts in relation to the parts around it, or you can call it objects and morphisms.
I might be totally wrong, again, or using the wrong words and confusing everyone including myself (which is why I like to study formal languages, too). But I think that no matter where you start from, you will eventually find yourself in a place where you are scratching your head, confused about what you know, what you don't know, what everyone knows, and what everyone doesn't know.
Oh, and it's probably totally obvious if write proofs, believe in induction, and get very philosophical.
(In case you don't know Lehrer, he did PhD studies in math at Harvard, and taught at Harvard and MIT, often performing his songs during his lectures (or composing songs FOR his lectures.))
I'm the right age to have done this when I started school. My memory is of it is playing with lots of wooden bricks that were marked with lines to show their length. It felt well taught but I'm not sure how well the rest of the class picked it up.
Interesting, I have no background in higher level math at all (stopped after high school calculus), yet still am able to grok Either, Maybe, Unit, etc., as I'm sure is the case with any non-math head that happens to be a programmer.
The difficulty I find with Haskell itself (setting aside FP basics that exist in many languages these days), is the math requirement. Why requirement? Well, it may be possible to use Haskell in isolation without knowing category theory and higher level math in general, but in the real world, Haskell libraries are in fact based on and assume a foundation in category theory and general understanding of higher level math (see the uber popular Lens library, Yesod, Conduit, or really any non-trivial library implemented in Haskell).
Hand wavy stuff like, "oh, you don't need to know that, it's all just simple building blocks", mixed with, "go read this paper [filled with unicode symbols that have no meaning whatsoever to someone without a background in higher level math]" creates a split message, on the one hand Haskell is simple; on the other, beyond complex.
I'd say that F#, OCaml, and Scala are all more accessible than Haskell just due to their placing less of a cognitive burden on the beginner. Learning Haskell feels like reverse engineering my mind.
Will be interesting to see how things play out, Haskell is moving fast and is clearly ultra popular here on HN, perhaps startups are already using Haskell in anger (i.e. over Rails, Play et al).
> I'd say that F#, OCaml, and Scala are all more accessible than Haskell just due to their placing less of a cognitive burden on the beginner.
I think that this is largely a documentation issue rather than a language issue; that is, while certainly its a language issue -- a strength -- that implementing things with a strong basis in (e.g.) category theory is facilitated in Haskell, its a documentation issue that many things implemented in Haskell libraries are not explained in a manner accessible to programmers who don't have that kind of background.
There is also the amazing and bewilderig Java Generics FAQ.
Lens actually has a great tutorial in its standard documentation. You aren't required to read all the theoretical foundations. Trying to explain the logic under JS truthiness will make your head just as spinny.
This book is what finally demystified category theory for me.
But as a fair warning it's role is as a synthesizing text for first-year PhD students in pure mathematics. The author's goal is essentially to prepare students to study algebraic geometry, which is one of the most obscure areas of contemporary mathematics research. That doesn't make it any less enjoyable of a book, and it has a lot of topics that are mostly unrelated to algebraic geometry. The point is it's not an easy book by HN standards.
While I know what you're getting at, I think of it as pretty accessible. It assumes a little familiarity with terminology, but since the goal is to use CT as a tool to "see" the structure of various mathematical objects it doesn't demand a whole lot of the reader in terms of background knowledge.
I suppose I should have begun by stating that CT is a new lens on the world and any reader interested in understanding it needs to have the, typically mathematics-derived, patience to really slow down and re-evaluate the way they view some friendly concepts. But I think even with that the "Socratic" rhetoric employed is helpful.
So, I totally agree but even if it's a bit off a waterfall it's not one that I feel too bad about encouraging people to jump off of.
I'm reading that right now. It's a very gentle introduction, and I do recommend it. I looked at some other books but they were very dense with notation that I hadn't seen since college. Conceptual Mathematics doesn't really presume any prior knowledge, so even if it's a little slow in some parts, it's helping me get back up to speed.
I was quite possibly one of them! I recommend Conceptual Mathematics at every opportunity. It's a wonderful first CT book. Aluffi is a bit more ambitious in scope—you leave with a broader understanding of abstract algebra at large as interpreted through CT when useful.
I agree with Jonnie...what books did you read? Your comment does a great job presenting math in a way that I would like to experience. What books/videos/materials did you discover that enhanced this?
Unfortunately there isn't a single publication that does justice to what I've pieced together. By that I mean, because I had such a poor understanding of math, every little bit of knowledge and intuition that most people learn implicitly, I had to learn explicitly. The downside is that it took me all this time to realize how useful math is, but the upside is that I now have created several explanations (both in text and video format) where I explain all of these intuitions in a piecemeal way, slowly building up a model of the world, but without any math notation and without ever talking about numbers, just objects in general and relationships between them. You can go from scratch (things you see around you) all the way to category theory without realizing you got there, all without notation, just building intuitions. That's what I do in the videos, I use the idea of a caveman looking around and starting to discover these relationships, and building on top of them.
I must have more than 15 hours of material that I recorded as I was piecing together what I was (and am) learning. I should put them online - I haven't done it yet because I think it drags on for too long, but maybe I should put up one or two and judge from the comments and go from there.
Mostly I gathered these ideas by first finding out that Set Theory is at the beginning of math. Then I found out how categories and types and sets are all equivalent. Then I read some papers that explained that and for that they needed to step back and give some intuition of each and how they relate to each other. I explored so many links, but the knowledge is scattered.
I will publish some of the stuff I made, now that I know there's interest, when I'm back home on Monday. If you want to know about it, send me an email (it's in my profile page) and I'll let you know.
Publish it. Don't get caught up in perfectionism. This would be highly valued by me and many others even if it does "drag on" at times or lacks polish in certain areas. You have just recently bridged a gap that many would like to bridge, so it is still fresh in your mind what it is like to be on both sides of that gap. It's that freshness that lends unique value to your material. A 20 year professor might be an expert, but she has lost that freshness.
Seconding this. Publish it, even if its a mess. Just make it CC, other people will clean it up if they think it's worth doing. If they don't, no loss to you.
As somebody who is looking for engaging ways to teach my young children math, I will also ask you to please please make this available. (And I can fully agree with previous comments regarding perfectionism and creative commons).
Wow, thanks for the interest :)
I will definitely publish it this weekend on Youtube (I'm not home right now so I don't have access to the files).
If you'd like to be notified about it, ping me on my email; I would love to have feedback on them!
How did learning how Algebraic Data Types are algebraic make you "get" Haskell?
When I learned Haskell, I just read Learn You A Hasekell in a few days, and immediately understood the practical value of Algebraic Data Types. They simply are like the types in C,Java,etc but more general because unions can have "fields". This alone means you can represent things like Maybe without any trouble, whereas in C/Java, you'd have to use casting, explicit tagged unions, or the visitor pattern. ML has largely the exact same features as Haskell, except you have to explicitly say which module you're using, instead of the typeclass system doing it for you. Do you also "get" ML? It sounds more like you are claiming to "get" some sort of theory, rather than Haskell or ML, which are trivial, but you make it sound like you need to be somehow enlightened to understand.
The only hard part I ever found in Haskell is lazy evaluation, which to me is just another type of magic which nobody gets, just like the Java Memory Model. The other hard part of Haskell are the extensions to type classes, which make you start thinking about open research problems.
edit: Which part of the above is downvoting material? Please explain so I can avoid being downvoted in the future.
I think there's reason to believe that ADTs are both a major component of "getting" Haskell and a major topic in their own right of significant size beyond Haskell itself.
> This is not a language for clever people, although there are clever things that can be done in this language. It is a language for simple things and clever things alike, and sometimes we want to be simple, and sometimes we want to be clever. But we don’t give bonus points for being clever.
I'm reminded of the adage about mathematics: think deeply of simple things.
I think there's a lot of value in this article (which really isn't about Haskell; but more generally about being in the top 5% of programming). I can't disagree with the idea that we should show more open-mindedness toward different approaches and civility to new entrants.
That said, I'm going to take a different tack, not because the OP is wrong, but just to explore a second orthogonal component.
As programmers, we have both a weak and a submissive tribal identity. That's a problem, and we should change it. I call it "weak" because we aren't good judges of who belongs and who doesn't. The true bad guys (and, yes, they are quite bad and we must oppose them) have been commoditizing engineering work for decades by flooding the market with low-skill, untrained, "software engineers" (ScrumDrones, CommodityJavaDevelopers, etc.) in order to reduce top talent's leverage in the market. It has created this mythology that talent and skill don't matter, and while it's completely wrong, the failures are delayed enough that the bad actors in the business can be promoted away from the problem until shit breaks.
Our fatal flaw? Instead of striking the bad actors in the business world, we attack those low-skill engineers, who might be infuriatingly incompetent, but really didn't do anything wrong. ("You're just a PHP retard, so shut the fuck up.") The true bad guys don't really care what happens to the CommodityScrumDrones, and that's the point of having them is that they're disposable. By attacking them, the unskilled pawns, we gain nothing. Sure, they're incompetent and may be anti-intellectual (or, more likely, they just don't give a shit about programming and shouldn't be programmers, but aren't stupid or bad people). But the anti-intellectualism we must fight is that of the businessmen who are driving us in to the ground.
I say it is a submissive tribal identity because this divide-and-conquer game works. Dysfunctional organizations and societies usually form three classes that matter. (There are subclasses within each related to prestige factors that don't matter.) The High must keep the Middle and Low at odds with each other, lest they band together and overthrow the High.
In order to depress programmer wages and working conditions, the bad guys prevent professionalization and collective bargaining, create startup mythologies in order to make business bad actors look like real technologists, and flood the market with commodity programmers (the Low). Amazingly, the more skilled programmers (the Middle) will, driven by their disgust in sharing working conditions with the Low, actually work unreasonably hard and clean up their messes, just to out-compete them in a game that doesn't really matter (the unskilled are never fired, and the overworked are rarely promoted). When this works as designed, they turn into the Clueless layer of the MacLeod model.
We have to fight the anti-intellectualism. We've let ourselves be typecast to business subordinates rather than technologists and it's goddamn fucking disgusting. When some businessman says "languages don't matter", we have to humiliate him for his stupidity and anti-intellectualism, before he feels empowered enough to start hiring commodity engineers. We do have to fight, and we have to get nasty, and we have to crush our enemies. But we also have to stop clawing at each other over petty differences (e.g. tabs vs. spaces) and focus on the battles that matter.
Interesting thesis. There's certainly a glut of minimally competent developers, many of whom end up at companies for whom software is an incidental concern and therefore lack sophisticated hiring practices.
But many of the top 5% are hired by software companies who depend on innovation for survival and seem to recognize the distinction between the CommodityJavaDeveloper and the PolyglotScientistEngineer (or whatever you want to call the other end of the spectrum). Either these companies will resist the pressure exerted by that ocean of lightly-trained 9-5 programmers or they will lose their edge and fail. And aren't those companies where we want to work anyway?
NOTE: I don't mean to disparage those who happen to work 9-5. Rather, I'm suggesting that the best programmers don't cease to be such when they go home at the end of the day.
There is no easy way around this if you really want a collection which is heterogenous, but often, you would just cook up a struct/record-like object for these things.
Trading off easy heterogenous lists buys you a better type checker, more static knowledge, faster programs and so on. It also has the advantage that mapping data into the system can be done safely. The price is that self-describing data (JSON, Transit, Msgpack, ...) is more unwieldy to work with - but a little combinator library, scrap-your-boilerplate-generics, or a reflective code generator goes a long way to solve that problem:
You seem to be implying that the generic lists shown in Python or Lisp are somehow unsafe. They must be since if we throw them away, or wrap them in some clumsy structs/records, we can "buy" safety. Even if that is the case, we cannot sell Haskell as some kind of semantically rich language for doing cutting edge research, when coding up basic things like this is a struggle. If I have to cook up things with structures, I might as well use C.
Here is another simple problem: divide two integers so that the result has integer type when the numbers divide evenly, otherwise rational type.
Extend your numeric type tower to handle whatever new numeric types I come up with in an internally consistent manner.
In haskell I have number types for things that automatically compute derivatives. I have number types for functions that go to number types so all vector spaces work like numbers as well. I have number types for arbitrary precision floating point numbers, and I can build these things on top of each other.
It is a trade-off. We give up a bit of one thing to get something else.
You can take either side of the deal. I'd argue that the weight of benefit is on the side where we don't have a magic type tower to reason about, but it is a perfectly reasonable stance to say that the thing you want is more important to you.
On the other hand, I can turn around and argue that if what I really want is an ad hoc tower of numeric types I can just make a type for that and work inside it.
data Number = Int Int | Rational Rational | Double Double | Complex (Complex Double) | ...
instance Num Number
Now I can opt into your model. Can you opt into mine?
You're totally right that there's a tradeoff here -- in Typed Racket, where we have strong types for the numeric tower plus the flexibility that the parent wants, arithmetic isn't extensible.
However, it's not the case that `data Number = ...` gets you everything. In particular, it gives up on the types! :)
For example, in Typed Racket:
-> (: norm : Real Real -> Real)
-> (define (norm x y) (sqrt (+ (sqr x) (sqr y))))
-> (norm -3 12)
- : Real
12.36931687685298
We've proved that the `norm` function always produces `Real` answers, even though `sqrt` might produce complex numbers given negative inputs. The sum type you've given won't let you prove that.
In Python, not only can you "opt in" to those features (in a completely natural way) but those features already exist in the form of highly popular libraries:
...and the story is similar with Common Lisp, whose generic functions dispatch on function parameter type (just like Haskell allows with type classes), allowing you to create libraries for vector arithmetic, symbolic algebra, and arbitrary precision floating point math, again in a completely natural style.
The best forms of language advocacy probably involve showing the great things you've done with a language and forgetting about comparisons to the competition. Build it, and they will come.
"The best forms of language advocacy probably involve showing the great things you've done with a language and forgetting about comparisons to the competition."
Great things the parent has done with the language:
I am by no means an expert, but I think that Haskell handles your second problem without blinking (because integer is a subtype of rational).
For your first problem, C doesn't help in the general case. If I got a JSON package, I don't know at compile time what the types are going to be, so I don't know how to lay out the struct.
If I don't know anything about the types, the only things I can (safely) do are put them in untyped collections or convert them to strings. I can't add them - they might not be numeric. I can't convert them to uppercase - they might not be strings. (I can do all those things if you're going to return a Maybe - and maybe that's the right approach if you got a JSON package over the wire.)
I don't see that they're a struggle. They are more verbose than with Python or Lisp, sure, but you gain something in return. On the other hand, you seldom find yourself needing to write those heterogeneous lists in Haskell, so what's the actual problem?
I am really interested to know why I would want such a thing. In years of programming, I have never needed a heterogeneous collection except in a dynamically typed language where I can’t express more precise types. My values are always related by some set of operations I want to perform on them.
In C++, for example, I might have a “vector<unique_ptr<GameObject>>” containing instances of various subclasses of “GameObject” such as “Player” or “Enemy”. “GameObject” has some virtual member functions such as “update()” and “render()”.
In Haskell I can do exactly the same thing with a “GameObject” type class containing the “update” and “render” methods, and implement “GameObject” for my “Player” and “Enemy” types.
In Python I do a dynamic check on every value in the collection, on every iteration, to see if “update” and “render” are present and callable. It just seems wasteful because you know that information ahead of time—a non–game object should never end up in that collection, so why waste brain power and computing power considering the possibility?
The difference being that if you expend the effort you can write a heterogenous collection that does is guaranteed to run for any input, whereas with Lisp or Python you must be very very careful about that because one false step and your program will blow up.
This doesn't jive with the observation that some Lisp programmers stay in the same REPL for weeks while experimenting with all kinds of new or undebugged code.
You are utterly missing the point. Of course any code that can be written in a type-safe manner in Haskell can be written in another language to perform the exact some machine operations. The point is that the compiler guarantees that this code will never break as long as the code compiles. In less type-safe languages you simply don't have these guarantees, no matter how careful you are, eventually someone will come along and break an assumption that kept the original code working.
You shouldn't consider this to be a break. Sure, it's crappy API design--lots of people have pointed out that `head` should return a `Maybe` because an empty list doesn't have a head--but triggering an error in a partial function is not a break. Taking the head of an empty list is no more a break than dividing something by zero.
I can't see any reasonable definition of "break" for this context for which that is valid; its exactly the same kind of breakage that strong type checking reduces the incidence of in Haskell compared to dynamic languages -- runtime errors resulting from a function call not being able to complete without error for all inputs that the language will allow to be passed to it.
> Taking the head of an empty list is no more a break than dividing something by zero.
I agree; both are clearly examples of things that can cause a program to break.
Good point, but in general I think it's fair to say that if Java's type system prevents the type of breakages that are possible in ruby 50% of the time, Haskell prevents 99.9% of such breakages.
I'm talking about maintenance, obviously you must make sure the code does the correct thing initially. I have maintained a 100k LOC Rails app for 7 years with near 100% test coverage. And guess what? Stuff breaks. 99% of the stupid breakages I have experienced would have been impossible in Haskell.
> What are you going to do with [1.0, "abc", True], besides throw a TypeError?
for x in [1.0, "abc", True]:
print(x)
Of course, all the legitimate things you can do with it illustrate ways in which the collection isn't really heterogenous, its just as collection of elements which have different types that are all within the same sum type.
The thing is that in dynamic languages, there's one universal sum type, and every function effectively takes arguments and returns results of that type. In Haskell, you have to plan more for the specific sum types you are going to be using, which in certain situations makes some things more complicated. Of course, it also means that things that would be in documentation or approximately verified in tests can be statically verified by the compiler, so there is a trade off.
But how did you get the collection in the first place? If all you wanted to do was print the elements, you would have made it a collection of strings, and populated it by calling a "toString" function each time you added an element.
"The thing is that in dynamic languages, there's one universal sum type, and every function effectively takes arguments and returns results of that type."
That is a reductionistic view, like saying that everything is ultimately ones and zeros. The storage place in a dynamic language, such as a variable, or array element or whatever, is not understood to have a type in that language. The machine language (or whatever) implementation kernel of that language understands that to have a type, but that's in a different language. That kernel knows that, say, if the least significant two bits of the storage location are 00, then it's a pointer to a heap object, and that kind of thing. That code must be written safely: like only if those two bits are 00 must it treat the value as a pointer, and otherwise not. This is all implementation detail, not accessible from the high level language (or not without special escape hatches). The type of the dynamic objects is their dynamic type; and when dynamic languages feature compile-time type inference, that inference works with those types, not with the fictitious "universal sum type".
> like saying that everything is ultimately ones and zeros.
Well, except that saying everything is ultimately ones and zeros isn't (at least in this context) a useful starting point for explaining anything.
> The storage place in a dynamic language, such as a variable, or array element or whatever, is not understood to have a type in that language.
I'm not talking about storage places, I'm talking about the logical design -- a function (regardless of the features of the language) is designed to operate on some set of values and return a result from some set of values. These sets can ar the types I'm interested in -- whether they are implemented as (static) types in a language, or as tags / dynamic types, or whatever, or even if the language had no concepts of types at all (and, in most real languages, and can be true true even withHaskell, as in the head function on lists).
And to the extent that "heterogenous" collections are useful, they are useful specifically because they are not really heterogenous, even if the shared logical type to which the elements must belong is not coherently defined as a discrete "type" within the type system of the language.
It's precisely a tuple, obviously. Are you sure you said "list", not "heterogeneous collection"?
If you know what is where in the list, then you semantically have a tuple.
If you don't know what is where in the list, then you need some way of telling things apart. At which point an ADT is frequently the right solution, isn't any sort of advanced technique, and requires very little in the way of boilerplate.
> Haskell wasn’t built on great ideas, although it has those. It was built on a culture of how ideas are treated.
> In functional programming, our proofs are not by contradiction, but by construction. If you want to teach functional programming, or preach functional programming, or just to even have productive discussions as we all build libraries and projects together, it will serve you well to learn that ethic.
> Believe in everyone, attack nobody, even the trolliest.
> If you make even the most modest (to your mind) mistake, be it in social interaction or technical detail, be quick to apologize and retract, and do so freely. What is there to lose? Only your pride. Who keeps track? Only you. What is there to gain? Integrity
> Your self-esteem doesn’t need your help. You may feel you need to prove yourself, but you don't. Other people, in general, have better things to do with their time than judge you, even when you may sometimes feel otherwise.
> Be glad that others are charting other paths! Who knows what they will bring back from those explorations.
> Every time we learn something new and want to share it, we face these issues all over again -- the desire to proclaim, to overturn received wisdom all at once -- and the worse the received wisdom, the more vehemently we want to strike out. But if we are generous listeners and attentive teachers, we not only teach better and spread more knowledge, but also learn more, and enjoy ourselves more in the process.