<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body bgcolor="#FFFFFF" text="#000000">
I came to Haskell from C++, and I was used to the idea of parametric
types and functions from C++ templates.<br>
<br>
However, what I really liked about Haskell's way of doing these was
that, due to type inference, not only is there a lot less ceremony
involved, but code is generic (parametric) *by default*, and thus
much more reusable, although you still have the option of tightening
it up by adding a type annotation (eg for performance reasons). For
a while, I was writing all my C++ code as templates, but this ended
up being a pain.<br>
<br>
Also, traditionally C++ has not allowed you to place any constraints
on template arguments (type parameters) whereas Haskell's type
classes are a very elegant way of doing it. (C++ now has concepts,
but I haven't taken the time yet to see how they compare with type
classes.)<br>
<br>
I was also used to function overloading, which is somewhat similar
to type inference, in that the compiler will pick an implementation
based on the types of a function's arguments. This is similar to
Haskell picking an implementation from among type class instances.
However, what blew me away is that Haskell can overload based on
*return type* as well as argument types. I haven't seen any other
production-ready language that can do this. A great example of how
this is useful is the regex library, where you can select from among
widely varying styles of regex matching result simply by type
inference, ie without needing any type annotation.<br>
<br>
There were a *lot* of other things I found amazing, but others have
covered many of these already. Also, languages are borrowing from
each other at a rapid rate these days (eg Rust traits are equivalent
to type classes) so it's hard to find a "killer feature" in Haskell
any more (except laziness, perhaps). I think it's more the
well-balanced combination of all the features that makes Haskell so
pleasant to work in, and it's hard to demonstrate all of these in a
single example.<br>
<br>
My own favourite "gem" is this code for computing all primes, based
on code in a paper[1] by Doug McIlroy:<br>
<br>
primes = sieve [2..] where sieve (p : ns) = p : sieve [n | n <-
ns, n `mod` p /= 0]<br>
<br>
I think care must be exercised, when using examples like this one,
to avoid giving the impression that Haskell is a "toy" language.
However, what I find interesting about this example is that all
other sieve implementations I've seen work on a fixed size of sieve
up front, and if you later change your mind about how many primes
you want, eg because you're expanding a hash table and want a bigger
prime for the size, you typically have to start the sieve from
scratch again.<br>
<br>
[1]: <a class="moz-txt-link-freetext" href="http://www.cs.dartmouth.edu/~doug/sieve/sieve.pdf">http://www.cs.dartmouth.edu/~doug/sieve/sieve.pdf</a><br>
</body>
</html>