

Is Haskell liberal or conservative? - malloc47
http://blog.ezyang.com/2012/08/is-haskell-liberal-or-conservative/

======
tzs
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.

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...](http://bentilly.blogspot.com/2010/08/analysis-vs-algebra-predicts-
eating.html)

Someone should start making sure that at catered events where hackers
congregate there is plenty of corn on the cob, and gather this data.

~~~
polymatter
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.

------
chwahoo
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).

~~~
tikhonj
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.

~~~
polymatter
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].

------
rabbitfang
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.

~~~
graue
Personally I appreciated this article (and the ensuing discussion) as a good
overview of the philosophies behind Haskell.

