I think a more interesting classification would be which languages are favored by people who eat corn on the cob typewriter style, and which are favored by people who eat it spiral style.
Thank you very much, I now know exactly what I'm going to do at my next hackers meetup. This clearly needs more datapoints.
From your link: "I know someone who got his PhD studying Haskell's type system. My prediction that he ate corn in rows was correct". This could very easily have been me too. I started a PhD working in Haskell's type system and I eat corn by rows too.
I'm not sure btilly's argument was entirely sound. On the reddit thread for this post (in /r/math) counterexamples seemed to outnumber examples. (Not that that is itself evidence that this phenomenon's real.)
Accepting Yegge's framework for purposes of this response:
Haskell is beyond conservative, but it does take great pains to try to address the reasons that people might want a more liberal language. However, it's often really painful to get that code to typecheck compared with the effort to get the same code correct in python or ruby. Sometimes Haskell is the worst of both worlds: it requires mind-bending reasoning to write "liberal"-like code, when the "conservative" guarantees you get in return aren't for very interesting correctness properties.
I'm starting to think my ideal language would be gradually-typed (something like Groovy): use static typing by default, but fallback to dynamic typing for the pieces that require superhuman effort to type correctly (unless you believe that the correctness guarantees from static typing pay off for the code you're writing--e.g., code in rarely exercised error handlers).
I'm curious what sorts of things you have in mind when you refer to "pieces [of Haskell code] that require superhuman effort to type correctly"? In my own Haskell experience, except when playing with silly and mostly pointless tricks like doing computations in the type system, I've never really felt like Haskell's type checking has been a hindrance. It's more like those inflatable bumpers on bowling lanes: it only stops me from doing the things that I wouldn't want to do anyway, like forgetting to check for failure conditions or allowing mutable state/side effects to seep into parts of my code that I intended to be pure.
> However, it's often really painful to get that code to typecheck compared with the effort to get the same code correct in python or ruby.
I'd argue that in the overwhelming majority of cases, the Python or Ruby code is equally incorrect to the equivalent Haskell code that doesn't type check, it's just that Python and Ruby don't tell you about it upfront, you find out about it at runtime. Hopefully, "runtime" means "during testing" and not after your code is in production. Or if you want to put a more positive spin on it, Python and Ruby let you run the code in spite of its lack of correctness. If that's the kind of freedom you want, then a dynamically typed language (or even a weak statically typed language) will suit you well. As for me, I've been burned by that "freedom" enough times now that I can't think of it as anything but a negative.
It's funny--I have exactly the opposite experience. Namely, I find it easier to write code in Haskell than Python or JavaScript, type system and all.
The type system actually makes the language more expressive, as odd as it may seem. For example, you can write code polymorphic on its return type. Even in trivial code this is nice--there is a dual to toString (called read) and constants like minBound/maxBound work for all applicable types.
However, this really pays off once you get to things like applicatives, monads and arrows. One of the reasons these abstractions are so useful--and they certainly are, letting one easily write shorter and more general code--is that you never have to specify what applicative/monad/arrow instance you're using manually. This means that there is essentially no syntactic overhead to using a type that's polymorphic like that! In a dynamically typed language, there would be no way to use it without somehow passing in or specifying what instance you want manually.
The type system also helps me by constraining the space of programs I'm searching through. Very often I write code that seems reasonable but doesn't work in subtle ways. An example from Python would be code that attempts to index a tuple but actually gets a string. In Python bugs like this--including exactly this bug :)--take me a long time and quite a bit of frustration to find. Once I've found them, fixing them is easy, of course, so the only problematic bit is figuring out exactly what the problem is. The Haskell type system catches a large portion of these sorts of mistakes as soon as I compile. All I have to do to get that code to work is to get it to compile, which is much easier than trying to debug some Python failing in an inexplicable way!
Also, the sorts of properties a good type system (e.g. Haskell's) can guarantee are not all trivial. Sure, it'll force you not to mistake strings for numbers. And this is, granted, boring. But it goes far beyond that! I can guarantee that no external code can implicitly modify my current function; this only works because the type system controls mutability. I can guarantee that calling some function in a test is safe because it won't write to the database or send emails (this is another problem I've had with Python!) or generate a ton of logs.
Let's take an example from work. At work, I'm using OCaml rather than Haskell, but the idea is much the same. I'm currently working on the command-line frontend to our program. Among other things, it allows you to specify inputs. Just like any reasonable tool, it can either take paths (actually arbitrary URIs) or just get input from STDIN. Initially, we were using strings to hold the uris. STDIN was represented with "-". This is essentially just like a dynamic language. Switching to a proper type for inputs had an immediate advantage--it pointed out every single place we forgot to handle STDIN as an option. Some of these wouldn't have been caught without extremely thorough testing and a healthy amount of luck.
Another interesting example is units. A good type system can actually help you encode what units a number is in. Mixing up numbers in cm with numbers in m or kg can create subtle, hard-to-find errors. With a sufficiently clever language, you can just get the compiler to figure it all out for you!
In Haskell, you can even use types to encode complex reasoning about the actual behavior of your code. This has two victories--you get the behavior in question for free and it gets reflected clearly in the type system. In particular, I'm thinking of monad transformers. If you want to write some backtracking code, you can encode using the list monad. If you want to write some code that could fail with some error, you can encode that with Either. But the real beauty is when you want to write backtracking code that could error. There are two possibilities: you either want any branch having an error to make the whole computation fail or you want each branch to be able to fail on its own. And you can actually encode this directly in your type! The order of transformers (that is, whether ErrorT or ListT comes first) controls the error behavior. Not only is it essentially trivial to switch from one behavior to the other, it's also clear which one you're using just from the type! This sort of code is both more expressive and safer than any alternative I've seen from a dynamically typed language.
In short: static typing à la Haskell not only catches nontrivial problems but also makes the language more expressive. I've found this to translate to code that is both safer and easier to write than the equivalent Python or JavaScript.
Just wanted to point out that this echos very much my experience with Haskell with one very important caveat. You actually need to have done the study to be fluent in Haskell's type system before you get this benefit.
And I'm not sure there is any better method than simply playing "how about now?" with Haskell's type system. While following (http://learnyouahaskell.com/)[Learn You a Haskell For Great Good].
Okay, but you're still talking from a Yegge-conservative standpoint; your language is helping you avoid risk. It's just that it does a very good job of it.
I really don't see why there is a need for everyone and their dog to respond to Yegge's rambling blog post. Is language [X] conservative or liberal is now littering the HN front page.
I'm not joking. Corn on the cob eating style among mathematicians has been found to be a strong indicator of whether that mathematician favors algebra or favors analysis: http://bentilly.blogspot.com/2010/08/analysis-vs-algebra-pre...
Someone should start making sure that at catered events where hackers congregate there is plenty of corn on the cob, and gather this data.