
The New Haskell Homepage - markthethomas
http://new-www.haskell.org
======
thoughtpolice
Please note this homepage is NOT final and it's going to see revisions before
we push it out to the actual website, including many tweaks to the content and
probably some styling tweaks too.

There are a lot of other things we still need to do as well, like ensure all
redirects and subpages work properly.

Source: I'm one of the Haskell.org administrators, and we pushed this out only
today.

~~~
Pacabel
Is there a practical reason why there's so much empty space with this new
design, and why so little valuable content and functionality is visible by
default?

Viewing the existing site in a desktop browser, I get to see the description
of Haskell, and a bunch of useful links about learning it, downloading an
implementation, using it, and participating in the community. Recent news
items and upcoming events are also visible, as is the search field.

This new design lacks pretty much all of that. Instead of useful content,
links and functionality, all I'm seeing are large areas of purple and white,
and an extremely blurry photo, along with content of very limited value.

I just can't see this new design being beneficial in any way. It makes it much
harder to get useful information about Haskell, which seems very contradictory
to what a website like this should be doing.

~~~
rtfeldman
Yes - the practical reason is to focus on the newcomer's experience.
Information overload is actively harmful to someone coming to haskell.org to
learn about the language from scratch.

Omitting content that is primarily valuable to experienced Haskellers is a
feature, not a bug.

~~~
Pacabel
This sounds like a dangerous trade off to be making. It's reminiscent of what
we saw with GNOME 3, or even Windows 8. The experience is made much worse for
existing users, in a vain attempt to "simplify" the design to allegedly appeal
to new users who may not even really exist in practice. It's obvious now that
it didn't work well in those cases, and I don't see why this case would be any
different.

As an occasional Haskell user, I'm served much, much better by the existing
site than by this new design. The existing one lets me get to the information
I'm looking for with minimal effort. This new site denies me that
accessibility, I'm afraid to say.

I don't see the point in trying to attract new users if doing so also means
harming the experiences of established users. Drawing in new users becomes
pointless if retention starts to suffer.

~~~
TuringTest
_" This sounds like a dangerous trade off to be making. It's reminiscent of
what we saw with GNOME 3, or even Windows 8."_

It's also reminiscent of what we saw with the iPhone, and nobody would say
that the experience was much worse for users of previous smartphones. There
are times when simplifying and giving structure to existing content just makes
sense.

I'm curious, what content do you miss from the old page that can't be found in
the Community or Documentation sections in the new design?

~~~
Pacabel
I'd like to see the Documentation, Community and News content on the front
page, rather than hidden away on those separate pages. The new design adds an
extra, unnecessary level of indirection in order to get to this useful
information.

~~~
TuringTest
Fair enough, but as other posters have noted there's no reason why those
contents need to be placed directly at the home page; they could be located at
an inner page that you'd bookmark for reference.

The purpose of a good landing page is not to serve as an index for all the
content (that's what site maps are for), but to explain the concept and
structure of the site to someone that haven't seen it before. The new page is
much better in that respect.

I miss a link to the current Haskell wiki in the new design, but I definitely
wouldn't expect to find a list of all the wiki pages on the land page, but
available under the Documents section.

~~~
Pacabel
I don't want to deal with numerous bookmarks to internal pages, or site maps,
or any crap like that.

I want to be able to type "haskell.org" into any browser, and from there be
able to quickly get to the standard library documentation, to the language
spec, to Planet Haskell, to the downloads, and so on, without having to dig
through subpages of subpages of subpages, and without having to scroll.

The Rust website at [http://www.rust-lang.org/](http://www.rust-lang.org/) is
a good example of how a programming language home page should be laid out.
There are many relevant links at the top. I can almost always find what I want
within the first inch or two of the page. Yet it still shows all of the
marketing junk for those who want that stuff, but it's placed well below the
useful content.

The new Haskell design is the complete opposite of that. It puts a lot of
useless junk front and center, and almost totally discards everything that
actually is useful.

------
ufmace
Well, it sure looks nicer, I'll give you that.

I'm more interested in the content, though. I was just trying here and there
over the last week or so to learn some Haskell - people always seem to be
raving about how cool it is. I found my way to the CIS 194 class link, the
first one on the page, and I find that it really isn't very good for learning.

I went through the first page, trying to run some of the stuff. I find that
the syntax of the ghci REPL seems to have almost nothing to do with the syntax
shown so far. Apparently, I have to use let for every variable, which was
never mentioned, and there are lots of funny tricks for how to use multi-line
stuff. I still have no clue how to actually write something, compile it, and
have some sort of output in the main ghc compiler. Is there a tutorial
anywhere that actually helps you learn the language through doing useful
things, instead of throwing a bunch of syntax that you can't do anything with
at you?

Speaking of tutorials, the old page links to like 500 of them or so. I have no
clue how to figure out which one to start with. If you're re-doing it, please
link no more than 3 learning pages, no matter what. Have the rest in some
buried page somewhere if you must, but keep the front page manageable. How is
anybody supposed to make sense of however many tutorials and courses you guys
have linked on the old one? I gotta figure I'm the prime audience for this
stuff, but I have no idea where to start on your current page.

While I'm at it, can anybody recommend something like a step-by-step thing for
people who are proficient in several other languages, but have never seen any
Haskell before? Like where every little step has something you can actually
type in, run somewhere, and get some sort of output?

~~~
sparkie
I too dislike tutorials focused around the REPL, because it's rarely how you
write code in practice. The REPL is more of a debugging tool for quickly
testing and manipulating code you've already written.

I'd jump directly into creating code files/modules - begin by creating simple
programs using `main` as you would in other languages. Create a file with
".hs" extension, (Haskell filenames start with capital letters by convention,
since they share the name of the module)

    
    
        main :: IO ()
        main = putStrLn "Hello World!"
    

Make sure the GHC bianries are in your PATH, and use the program "runhaskell
File.hs" to quickly compile and execute them. Also, from ghci you can use the
command (:load File.hs), if you want to debug stuff.

The preferred tool for writing Haskell though is emacs. If you're not familiar
with emacs, its also a great opportunity to learn. Grab emacs 24, and open the
file ~/.emacs, paste in this snippet:

    
    
        (require 'package)
        (add-to-list 'package-archives
                 '("marmalade" . "http://marmalade-repo.org/packages/"))
        (package-initialize)
    

Then hit M-x (M for Meta, which is typically Alt), and type _eval-buffer_ into
the minibuffer at the bottom. If no errors, hit M-x and type into the mini-
buffer:

    
    
        package-install haskell-mode
    

You can add the following to the .emacs file and use `eval-buffer` again. Also
save with C-x C-s.

    
    
        (add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)
        (add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
    

Next step is to just open an empty haskell file. Create a new directory for
your project with `M-x make-directory`, and create a new haskell file using
C-x C-f. Add some code, and hit C-c C-l (load in ghci), and emacs will pop
open a new window, launch ghci and load your code into it.

You can switch over to the ghci window with C-x o (cycle windows), and type
some code into it for testing. (Note it can be quite buggy if the cursor is
not in the right place - there needs to be a space after the prompt > ¦).
Useful keyboard shortcuts to remember here are M-p (previous) and M-n to cycle
through previously used commands. (You can rebind any keys to how you wish.)

You can also add typicall IDE features like "run without debugging" and such
with simple snippets of elisp. Say if we want to bind F6 to this command, we
can add this hack to .emacs, save and eval the expression.

    
    
        (global-set-key [f6] 
            (lambda () 
                (interactive) 
                (async-shell-command (concat "runhaskell " buffer-file-name))))
    

Now with an active haskell file, F6 will launch like an application, bypassing
GHCI - and emacs will typically open a new window (or replace an existing one)
with the stdout/stderror for the application.

That'll get you started anyway. From there, using LYAH is a good beginner
resource, although it won't get you much further than past the syntax and
semantics of the core language. It doesn't cover the plethora of language
extensions, building projects, using cabal, haddock, quickcheck and more. I'm
not aware of a single resource which covers these though - I just learned what
was needed as and when by searching - the best information typically comes
from one-off blogs focused on a specific problem.

~~~
ufmace
Thanks for the help, though Vim is already my choice for insanely-powerful
text editor with 2k+ page user manual :) I tried emacs, but the dependence on
the control key for everything makes it kinda painful on every keyboard I
have. I suppose I could probably remap a bunch of keys or something, but Vim
seems to work much better in the default configuration. I know this tends to
be a big flamewar subject, so it is what it is.

Anyways, your Hello World and runhaskell are much more along the lines of what
I'm looking for. Also checking out the other people's suggested Learn you a
Haskell.

~~~
happimess
> Also checking out the other people's suggested Learn you a Haskell.

Just to get the minority opinion out there, I found the style of Learn You a
Haskell to be insufferable. Real World Haskell is available free online[1] and
has a straightforward tone of voice.

[1] [http://book.realworldhaskell.org/](http://book.realworldhaskell.org/)

~~~
trevorhartman
I found Learn You a Haskell to be one of the best programming books I've ever
read and no I'm not joking. It's a work of art.

------
hss54
Please, get rid off the primes example, as it is horrible inefficient (in the
sense of, "Ok, let's find the first n primes by a simple well-known algorithm,
like the Sieve of Eratosthenes") and a simple (non-pure) array-based approach
will kick its ass.

Such a toy-example just contributes to the wrong belief that Haskell is just
useful in academics or teaching. Some time ago I did implement the sieve in
several languages and I also considered Haskell but set for an unpure approach
(IOUArray) and it was extremely fast (getting close to C/C++ and outperforming
Go, Java, etc.). Obviously such an example is not good to present Haskell's
novel ideas but this toy example is worse then no example.

edit: Sorry, did not want to appear nit-picky, I like the language and the new
design.

~~~
exDM69
> Please, get rid off the primes example, as it is horrible inefficient (in
> the sense of, "Ok, let's find the first n primes by a simple well-known
> algorithm, like the Sieve of Eratosthenes") and a simple (non-pure) array-
> based approach will kick its ass.

The primes example may be a bit awkward for people with no background in math
but it's also an excellent example to demonstrate lazy evaluation in Haskell.

The interesting bit is that primes is an _infinite_ list, containing _all_
prime numbers. Don't try to print the whole list or count the sum unless you
have a computer with infinite memory :)

~~~
autodidakto
Even though it's a good example, I think extra care should be taken to avoid
the stereotype that Haskell is elegant for math and academic stuff but not for
the real word.

------
ufo
It bugs me a bit that the example code is brute force trial division instead
of a true prime sieve. Sure, it highlights lazyness but the algorithm is less
efficient.

[http://www.cs.hmc.edu/~oneill/papers/Sieve-
JFP.pdf](http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf)

~~~
throwaway_yy2Di
Well it's the haskell.org landing page, of course they're showing off the type
of code that Haskell is good at. In your link, the purely functional version
(15 lines around a priority queue) is _more_ complicated than a naive version
with a mutable array, so why would they advertise it?

~~~
tel
I personally think the priority queue one is somewhat simpler than a fixed
array algorithm. It also produces an infinite list of primes (or generator)
instead of the primes up to a particular number. This is especially important
in Haskell.

I'd love to see it as it shows off some great data structures available in the
libraries (like priority queues) but it's getting longish.

The mutable array version is basically the same as imperative code everywhere

    
    
        sieveUA :: Int -> UArray Int Bool
        sieveUA top = runSTUArray $ do
            let m = (top-1) `div` 2
                r = floor . sqrt $ fromIntegral top + 1
            sieve <- newArray (1,m) True
            forM_ [1..r `div` 2] $ \i -> do
              isPrime <- readArray sieve i
              when isPrime $ do
                forM_ [2*i*(i+1), 2*i*(i+2)+1..m] $ \j -> do
                  writeArray sieve j False
            return sieve
    

It's a bit noisy syntactically and doesn't show off as much interesting stuff.

------
matchu
Neat! A nitpick: I haven't used Haskell, so I'm trying to read the prime sieve
example in the corner, but there's very little contrast between the background
and the nonalphanumeric characters. Some brighter syntax highlighting would be
a better choice against that dark background.

~~~
Touche
Also maybe pick a simpler example and not play into the stereotype that
Haskell is for people who think they are smarter than everyone else.

~~~
vamega
Could you suggest a simpler example?

Finding primes is something that is taught in the first programming class in
Indian high schools. I guess I've never thought of it as something hard.

I looked at nodejs.org, and their first example is a web server! Python has
the Fibonacci as it's second example (the first one show's numeric
operations).

Ruby does simple string operations on it's home page. While I think that is
indeed simpler, it's a little nuanced in Haskell. Depending on how you're
doing it you'll need to Map toUpper from Data.Char or use toUpper from
Data.Text, and I don't think it's a good first impression have something that
uses Data.Text, and the OverloadedStrings extension.

PS - Although, I do agree with some other commentors here that this code isn't
actually the Sieve of Eratosthenes, and is far more inefficient, and that is a
valid reason to replace that example.

~~~
tel
Well, for one, it's a bad sieve algorithm.

I think a neat algorithm to demonstrate laziness and Haskell clarity would be
enumerating the Calkin-Wilf rationals. [0] It's quite a bit longer but
demonstrates a _number_ of neat ideas. I'll start first with a derivation
which demonstrates all of the structure of the algorithm and then go through a
series of mechanical transforms so that by the end I have a one-liner and a
comparable Python implementation.

The first algorithm comes directly from the paper and uses an intermediary
infinite tree to represent the rationals.

    
    
        data BTree a = Node a (BTree a) (BTree a)
    
        fold :: (a -> x -> x -> x) -> BTree a -> x
        fold f (Node a l r) = f a (fold f l) (fold f r)
    
        unfold :: (x -> (a, x, x)) -> x -> BTree a
        unfold f x = let (a, l, r) = f x in Node a (unfold f l) (unfold f r)
    
        breadthFirst :: BTree a -> [a]
        breadthFirst = concat . fold glue where
          glue a ls rs = [a] : zipWith (++) ls rs
    
        allRationals :: Fractional a => [a]
        allRationals = breadthFirst (unfold step (1, 1)) where
          step (m, n) = ( m/n, (m, m+n)
                             , (n+m, n) )
    

In 16 lines I've got an infinite binary tree, its natural fold and unfold, a
breadth first search, and a lazy algorithm for generating all of the rationals
with no repeats. The whole thing is simple, natural, beautiful, and efficient!
It demonstrates infinite recursive types, laziness, higher-order functions,
and bounded polymorphism.

And also a neat algorithm!

The downside is that 16 lines is pretty long.

By inlining the fold and unfold I can get it down to 9 lines:

    
    
        data BTree a = Node a (BTree a) (BTree a)
    
        breadthFirst :: BTree a -> [a]
        breadthFirst = concat . glue where
          glue (Node a ls rs) = [a] : zipWith (++) (glue ls) (glue rs)
    
        rats :: Fractional a => [a]
        rats = breadthFirst (generate (1, 1)) where
          generate (m, n) = Node (m/n) (generate (m, m+n)) (generate (n+m, n))
    

If I'm allowed imports we can use Data.Tree and make this a one-liner!

    
    
        import Data.Tree
    
        allRationals :: Fractional a => [a]
        allRationals = flatten (unfoldTree step (1, 1)) where
          step (m, n) = ( m/n, [ (m, m+n), (n+m, n) ] )
    

Finally, if I go another route and fuse the fold and unfold together into a
hylomorphism

    
    
        data Trip a x = Trip a x x deriving Functor
    
        hylo :: Functor f => (f b -> b) -> (a -> f a) -> a -> b
        hylo phi psi = phi . fmap (hylo phi psi) . psi
    
        allRationals :: Fractional a => [a]
        allRationals = concat (hylo glue step (1, 1)) where
          glue (Trip a ls rs) = [a] : zipWith (++) ls rs
          step (m, n) = Trip (m/n) (m, m+n) (n+m, n)
    

we can hide the tree entirely and demonstrate `deriving`... at considerable
cost to clarity! With a little more golfing (read: inlining) we arrive at this
beauty:

    
    
        allRationals :: Fractional a => [a]
        allRationals = concat (go (1, 1)) where
          go               = glue . next . step
          next (a, b, c)   = (a, f b, f c)
          glue (a, ls, rs) = [a] : zipWith (++) ls rs
          step (m, n)      = ( m/n, (m, m+n), (n+m, n) )
    

which at least has the bonus of demonstrating some nice co-recursion between
go and next. Or even, ultimately:

    
    
        allRationals :: Fractional a => [a]
        allRationals = concat (go 1 1) where go m n = [m/n] : zipWith (++) (go m (m+n)) (go (n+m) n)
    

which is actually kind of nice again if almost all of the structure has
vanished.

Note that if `interleave` were part of the Prelude then we could write

    
    
        allRationals :: Fractional a => [a]
        allRationals = go 1 1 where go m n = (m/n) : interleave (go m (m+n)) (go (n+m) n)
    

given

    
    
        interleave :: [a] -> [a] -> [a]
        interleave []     ys     = ys
        interleave xs     []     = xs
        interleave (x:xs) (y:ys) = x : y : interleave xs ys
    

which is a little prettier and directly comparable to something Pythonic like

    
    
        from fractions import Fraction
        from itertools import islice
    
        def interleave(x, y):
          while True:
            yield x.next()
            yield y.next()
    
        def all_rationals():
          def go(m, n):
            yield (m/n)
            for v in interleave(go(m, m+n), go(m+n, n)):
              yield v
          return go(Fraction(1,1), Fraction(1,1))
    
        def rationals(n):
          return list(islice(all_rationals(), n))
    

[0]
[http://www.cs.ox.ac.uk/jeremy.gibbons/publications/rationals...](http://www.cs.ox.ac.uk/jeremy.gibbons/publications/rationals.pdf)

~~~
gipp
It's also utterly incomprehensible for someone who hasn't seen Haskell before.
Whereas with the existing example, one can at least piece together an idea of
what's going on.

The point is to demonstrate the directness of expression and conciseness of
Haskell, not to show how to create an efficient implementation of an involved
algorithm.

~~~
tel
I agree that the first formulation is a bit incomprehensible, though two-liner
breadth-first search is understandable if a bit amazing.

Some of the latter versions (and perhaps ultimately the very last version) are
easier to walk through for a beginner, though, and are _calculated_ from
properties expressed in the first.

------
forrestthewoods
I get paid to write C++ code. I'm pretty good at it. I understand it's normal
usage syntax very well. I don't fucking know what a god damn thing means in
Haskell.

λ 5 + 7 12 :: Num a => a

What the christ? The 12 I get. Got it. The colons? Not sure. I think it's just
a dumb separator. Num is type! What the hell is a => a? I have no idea.

In the top they have an example.

primes = sieve[2..] where sieve (p:xs) = p : sieve [x | x <\- xs, x `mod` p /=
0]

Jesus. Where to begin? First of all I had to consult a dictionary for sieve. I
guess primes is a thing (function?) that takes 2 or more things? Not sure. Not
sure what 'where' means in this context. Don't have a good guess. Have
absolutely no fucking clue what "p:xs" means. Also no idea what "p : sieve"
means. I am equally stumped as to what "[x | x <\- xs," means. The "x 'mod' p"
I can guess! The /= 0 I'm not sure. Maybe "/=" is equivalent to "!=" ?

And here's the thing. I've tried to read a dozen or so tutorials on Haskell
and I give up every time because the syntax isn't explain. Please, please for
the love god just tell me what your abstract symbols represent!

Edit: [http://learnyouahaskell.com/](http://learnyouahaskell.com/) Reading
that now. So far it's pretty good.

~~~
gamegoblin
Ok I'll take a stab at a super high level crash course:

A note! Haskell has weird syntax. But it actually uses this syntax in cool
ways, as opposed to some languages that have weird syntax in an effort to be
different.

Let's consider the basic unit of Haskell programming -- the function!

Here is a function which returns its input:

    
    
        f x = x
    

Notice that there are no parens or types or anything. Since functions are used
so heavily, polluting them with parens would make your code look uglier than
lisp.

Now notice that I didn't include a type signature. In haskell, you can omit
them if you want. The compiler will figure out the most general type. Think of
this as C++11 `auto` keyword on steroids.

If I were to include the type signature, it would look like this:

    
    
        f :: a -> a
        f x = x
    

Let's break down those symbols.

`::` just means "is of the type". So `f :: ...` is "function f is of the
type..."

`a` is a type variable. Think of this like C++ templates! In C++, an
equivalent function is

    
    
       template <typename T>
       T f(T x) { return x; }
    

Where `T` is the same as our `a` in Haskell. In Haskell, it's common to use
the first few letters of the alphabet for type variables.

The `->` syntax is a bit funny, but it makes sense when you learn about
_function currying_ , which I will not explain now because it can be
intimidating to some. For now, just think of the type signature as

    
    
        arg1Type -> arg2Type -> ... -> argNType -> ResultType
    

So for our function `f` of type

    
    
        f :: a -> a
    

That means "The function f takes some argument of type `a`, and returns a
value of the same type `a`"

Now let's consider a more complex function.

    
    
        f x = 2 * x
    

As you can see, this is a doubling function. It takes a value and doubles it.
We can imagine that the value it takes can't be any arbitrary type, because
not all types can be doubled! So it doesn't make much sense to pass in a
string.

In Java style, we might say that the type must implement the interface
`Multipliable` or something. It turns out, Haskell has a system that is very
roughly similar to Java interfaces or in C++, a class with a bunch of virtual
methods.

Haskell calls these Typeclasses. So there is a typeclass that specifies that
types in the typeclass must implement some basic numeric methods, such as +,
-, etc. This typeclass is called `Num`.

So we can imagine, our doubling function _only_ takes types that implement
`Num`. Our type signature reads:

    
    
        f :: Num a => a -> a
        f x = x * 2
    

So everything between the :: and the => is typeclass specifications. So in
this one, I just specify that type `a` must implement `Num`. Let's say I also
required `a` to have the equivalent of a Java `toString` method, I would say:

    
    
        f :: (Show a, Num a) => a -> a
    

So now `a` must have a `toString` style method and must have numeric methods.

Now we are ready to approach the `primes` bit.

The first foreign looking thing is [2..]. This is an _infinite_ list from 2 to
infinity. How can one have an infinite list? The answer is laziness.

Whenever I go and ask for the 10000th value, the list must extend itself to
that value if it hasn't yet. So the list only grows for as much as you ask
for, but in theory it will grow until you run out of memory.

The [m..n] syntax is just nice syntactic sugar because it's used so much.
[1..10] == [1,2,3,4,5,6,7,8,9,10]

[1..] == [1,2,3,4,5,....infinity]

So this is what we know so far:

    
    
        primes = sieve [2..]
    

Which means "primes is equal to the function sieve, called on an infinite list
from 2 to infinity"

Now you ask, well what the hell is the function `sieve`?

Haskell has a nice sugar for defining scoped functions within other functions
with the `where` keyword.

Consider the doubling function. I could instead do:

    
    
        f x = x * (three - one)
          where
            three = 3
            one = 1
    

So it just let's you define values that get used in the function body in a
convenient place. This is akin to math jargon where people say "blah blah x
something blah where x is blah".

So `sieve` is a scoped function (cannot be accessed from outside of `primes`
that takes a list as an argument and apparently produces the primes that are
in that list. How does it do it?

We see some weird syntax in the definition of `sieve`:

    
    
        sieve (p:xs) = ...
    

What is this? It's pattern matching. Let me use fake C++ as an example.
Consider the recursive factorial function:

    
    
        int fact(int n) {
            if(n == 0) return 1;
            return n * fact(n-1);
        }
    

Now imagine if C++ let you do this instead:

    
    
        int fact(0) { return 1; }
        int fact(int n) { return n * fact(n-1); }
    

That is, you make a special case function body when the argument is 0. At
runtime, if the arg is 0, it uses the special case body, otherwise it falls
through to the general body.

So in Haskell, we could implement factorial like

    
    
        fact :: Num a => a -> a
        fact 0 = 1
        fact n = n * fact (n-1)
    

Very clean and sexy! But now you say "Yeah, but I could just use an if
statement or a switch..."

Now we go into the funny syntax and power of that funny syntax! Not only can
pattern matching match on values, but it can decompose those values. What do I
mean? Again, let me use some fake C++ as an example.

Consider the C++ function

    
    
        int f(pair<int, int> my_pair) {
            int x = my_pair.first;
            int y = my_pair.second;
            return x*y;
        }
    

Ignore that there is no real reason to pull the values out into `x` and `y`.
In a more complex function, I'm sure you can understand why it would be
tedious to type `my_pair.first` over and over again and we would want to pull
it into `x` or something.

Now imagine if C++ let us do this:

    
    
        int f(pair<x, y>) {
            return x*y;
        }
    

That is, f takes a pair, and _in the type declaration_ we decompose the pair
into its first and second parts, assigning them to the variables `x` and `y`.
In Haskell, this is trivial.

Consider a direct translation of the C++:

    
    
        f :: (Int, Int) -> Int
        f my_pair = fst my_pair * snd my_pair
    

Now the idiomatic Haskell, with pattern matching decomposition:

    
    
        f :: (Int, Int) -> Int
        f (x,y) = x*y
    

Slick, right?

So what is `sieve (p:xs)` decomposing?

In Haskell, the default [] list is a linked list (there are random access
arrays in various libraries). That means we can stick a value onto the front
of the list in O(1) time. The way we stick a value onto the front of the list
is with the `:` operator.

So

    
    
        x = [1,2,3]
        y = 0:x
    

`y` is now [0,1,2,3]

Just like we can compose lists with the `:` operator, we can _decompose_ them
via pattern matching with it.

So consider the function (I'll omit the type signature for brevity)

    
    
        f (p:xs) = print (p, xs)
    

Let's say we give `f` the argument [1,2,3,4]. What call to `:` would we have
to make to get this list?

    
    
        [1,2,3,4] == 1:[2,3,4]
    

So when we send [1,2,3,4] into `f`, it gets decomposed into ` 1:[2,3,4] `
where 1 gets put into `p` and [2,3,4] gets put into `xs`.

This is a very common idiom in Haskell. Let's say I wanted to make a function
that added 1 to every value in a list. Ignoring that there are much
cooler/efficient ways to do this in Haskell, let's make a specialized function
for it.

    
    
        addOne (x:xs) = x+1 : addOne xs
    

So let's read through that. In our pattern matching decomposition, we pull off
the first value of the list and store it in `x`, and we take the rest of the
list and store it in `xs`.

Now in our function body, we recompose a list with different values. Those
values are `x+1` for the first value, and `addOne xs` for the second value. So
we add one to the first value, and stick it into the front of the rest of the
list after the rest has had 1 added to its values. You might notice now, that
there is no bottom-out case for this recursion. So let's add one.

    
    
        addOne [] = []
        addOne (x:xs) = x+1 : addOne xs
    

So we pattern match to catch the special case of the empty list, which returns
the empty list, and then we decompose the general case as previously
explained.

So `sieve` is pulling off the first value, storing it in `p`, and taking the
rest of the list and storing it in `xs`.

It is returning...

    
    
        p : sieve [x | x <- xs, x `mod` p /= 0]
    

So, that is `p` stuck onto the front of...

    
    
        sieve [x | x <- xs, x `mod` p /= 0]
    

And we know that sieve returns all of the primes within its argument, so in
English...

    
    
        p stuck onto the front of all the primes in [x | x <- xs, x `mod` p /= 0]
    

So now what the hell is [x | x <\- xs, x `mod` p /= 0]? It is a list
comprehension.

Hackernews said my comment was too long. Read the rest here:
[http://pastebin.com/UesYMjjJ](http://pastebin.com/UesYMjjJ)

~~~
codygman
Wow, you should turn this into a tutorial on FPComplete or something. Maybe
there could be an "explain" link under the Haskell example on the homepage and
it link to a tutorial like this one.

~~~
gamegoblin
I'm actually recoding my website right now with a webserver and framework I
custom built in Haskell. Maybe I'll make some of my first posts on this topic
in a more formal, less commenty manner.

~~~
dbenamy
But the commenty style is awesome!

------
oneandoneis2
A few thoughts:

It's really distracting that typing in the REPL changes the size of the
containing div.

The blurry photo of (I assume) the audience of a lecture just doesn't work -
what's it supposed to do?

There's very little useful information - everything is at least one click
away. If the whole purpose of the site is to 'sell' to a new audience then I
guess that's not an issue, but I expect to be able to go to the site of a
language & get very quickly and easily to useful manual/wiki pages explaining
whatever feature I'm having trouble with.

The basic style is very 'modern' but it looks more like a Kickstarter page
that's there to sell you something trendy and new than the front page of a
site giving you information about a language. It's very pretty but (to me)
sends completely the wrong message about what this site is.

~~~
Torn
Also typing in their code example (the one right at the top, pride of place)
into their 'Try it' repl throws an error:

    
    
        primes = sieve [2..]
            where sieve (p:xs) = 
              p : sieve [x | x <- xs, x `mod` p /= 0]
    
        <hint>:1:8: parse error on input `='" error
    
    

Now I have almost no knowledge of Haskell, so I'm probably making some really
basic mistake, but I figure most visitors will try that and then get put off

~~~
thomasahle
Yes, that's certainly an issue. In fact the "Try it" box also seems to work
differently from the standard haskell live interpreter, in which you'd be able
to define functions by prefixing them with 'let '.

If you still want to try it out, say

    
    
        let sieve (p:xs) = p : sieve [x | x <- xs, x `mod` p /= 0] in sieve[2..]

------
cordite
Another suggestion would be more examples under the clear concise code bit--
possibly in a carousel.

Additionally, all examples could be loaded into the "Try It" section, so I
could type `take 4 primes` or something.

Instead, in my attempt to load the primes function.. I was met with this bit.

    
    
        λ let sieve (p:xs) = p : sieve [x | x <- xs, x `mod` p /= 0]
        can't find file: Imports.hs

~~~
groovy2shoes
I agree, but I'd go even further: make the example in the corner _actually
tryable_ the "Try It" section.

For this example:

    
    
      primes = sieve [2..]
          where sieve (p:xs) = 
            p : sieve [x | x <- xs, x `mod` p /= 0]
    

I tried to type it into the shell:

    
    
      λ primes = sieve [2..]
      <hint>:1:8: parse error on input `='
    

It doesn't work. Okay, what if I copy and paste?

    
    
      λ primes = sieve [2..] where sieve (p:xs) = p : sieve [x | x <- xs, x `mod` p /= 0]
      <hint>:1:8: parse error on input `='
    

Doesn't work.

Now, I know enough about Haskell to know what I can and can't type into ghci,
but what about people who are encountering Haskell for the first time? They'll
try to run the given example in the "Try It" section and will get nothing but
errors. Just my two cents.

P.S. Is Haskell still avoiding success at all costs? (A philosophy I continue
to be okay with, but it seems to getting futile :) )

~~~
axman6
Haskell is still avoiding (success at all costs), the bracketing is very
important. Haskell may seem like a slow to develop language and community at
times, but this is because most users want to see well thought out solutions
to problems, and if they have theoretical backgrounds showing that what
they're doing is a good idea, even better.

------
sparkie
> How often do programs crash because of an unexpected null value? Haskell
> programs never do!
    
    
        > head []
        error "Prelude.head: empty list"
    

Ok, so you don't call it `null`, but it still crashes the program. Its
deceptive to claim null isn't present because it's conventional to avoid using
"error" in favor of Maybe, but it's still there, and used throughout Prelude.
The REPL on the site hides these errors too, which is going to be pretty
confusing to a newcomer who takes the head of the empty list and gets back
"null" (the absence of a value) of type a.

    
    
        > (head x) + (head (head x))
          :: Num a => a
    

Hiding errors makes it hard for a beginner to see what went wrong, although
perhaps not in this trivial example.

~~~
wtetzner
There's a difference between crashing and returning null. If head returned
null on an empty list, that null could be passed around to different places in
the program before it crashed from a null pointer exception.

There can be unexpected crashes in Haskell, but not because of null.

~~~
sparkie
It's not equivalent to null, but analagous to it. With lazy evaluation, I can
pass also around the expression `head []` to different places, and it won't
complain until I attempt to evaluate it - much like a language with null won't
complain until you try to dereference it. Sure there's a difference though -
you can see immediately where the problem is with Haskell's error, but it's
more difficult to trace why a value might be null in imperative code (Which I
think has more to do with mutability than the presence of null).

I was also highlighting that the tryhaskell REPL actually behaves like null,
because it doesn't terminate immediately as you would expect.

Just yesterday I was discussing this topic with the author of the Mars
language, because his record implementation is equivalent to Haskell's and is
flawed in the same way (sum types + records leading to what is effectively the
equivalent of `null`)
[[https://news.ycombinator.com/item?id=8005116](https://news.ycombinator.com/item?id=8005116)].
Given a new language like Mars, he could provide a fix, but we have too much
baggage to break Haskell's implementation.

~~~
wtetzner
> With lazy evaluation, I can pass also around the expression `head []` to
> different places, and it won't complain until I attempt to evaluate it -
> much like a language with null won't complain until you try to dereference
> it.

It won't complain until you try to evaluate it temporally, but the stack trace
will point to the call to head.

------
sordina
I'd either link from the heading, or add some variety to the "View examples"
links.

Possibly something like:

    
    
        * Show me a world without Null
        * How does Haskell help me scale?
        * When does less code give me more?
        * Take me on a tour of Hackage

~~~
judk
This would be a massive improvement.

------
mintplant
This appears to be a continuation of chrisdone's work on an "alternative
Haskell homepage" [1], which was previously posted to HN [2].

[1] [http://chrisdone.com/posts/haskell-
lang](http://chrisdone.com/posts/haskell-lang)

[2]
[https://news.ycombinator.com/item?id=7814354](https://news.ycombinator.com/item?id=7814354)

~~~
TuringTest
Yes, the new page is signed by Chris Done at the bottom. I'm glad the
Haskellers listened to his advice and accepted the proposed design; now it's
time to tweak it with some real use.

~~~
chrisdone
I didn't put that signature there, whoever deployed my repo did. I've asked
several people to remove it.

------
k2enemy
Great timing, as I've just started to explore Haskell in the last few days.

First, I really like the style of the new site. My only gripe is that the
section with the lecture hall photo and the videos right below it don't seem
like an efficient use of prime real estate (and there is no context for the
videos, I have no idea what they are or why I would want to watch it. The
thumbnails suggest that I'd be clicking on an hour long lecture.). As a new
user, I'd rather see the features in this space.

~~~
lallysingh
Yeah, perhaps replacing those videos with a gallery of places to start
learning. Website previews, book covers, etc.

------
misnome
The box for "Try haskell expression here" is a little confusing, I tried to
click on the white area to focus and didn't get any response. You apparently
have to click on the same line, near the lambda symbol to focus?

Edit: Additionally, I really miss the lovely download page
[http://www.haskell.org/platform/](http://www.haskell.org/platform/) \- and
the non-home pages feel a little underwhelming and underdeveloped in general.

------
cordite
The "Try It" section really needs to have the text cursor be active anywhere I
can click on the box to type. At first it made me think that I had to move
over to the grey bracket-cursor (and thus a little
frustrating/confusing/unexpected). Especially since I can click to the right
(when the cursor is a normal pointer) and it gains focus.

This page is strongly trying to convert a viewer, the experience can be
smoothed here.

------
Tyr42
I feel like the sieve is a poor example, since it's not actually the same
algorithm as a sieve, and has a worse running time. It is possible to write a
very nice lazy infinite sieve.

See O’Neill's "The Genuine Sieve of Eratosthenes" paper for details.

[http://www.cs.hmc.edu/~oneill/papers/Sieve-
JFP.pdf](http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf)

~~~
judk
It fits the tradition established by the quicksort that isn't really a
quicksort.

~~~
axman6
That example does match some high level definitions of quicksort; "pick a
pivot element (the first element of the list), split the rest of the list into
elements less than and greater than or equal to the pivot, quicksort those
recursively, then reassemble the lesser, pivot and then greater elements". But
I do agree it's not quicksort as it's usually known with its in place sorting
and O(1) extra storage.

------
rtfeldman
Love it! Looks like all that's missing are the "View Examples" links under the
features.

One note: the quick walkthrough mentions "up there" in reference to the repl,
but the repl is actually to the left of that text when viewing on a non-
mobile-sized screen. It should probably just not mention the relative
positioning.

I suspect Fibonacci would be a more familiar code sample than Sieve, no?

------
brianbreslin
Would love to see a " this is where to use Haskell and why guide" just
something a novice can see and say "oh this is why I should learn this instead
of x"

------
austinz
I like the new site. It's beautiful and elegant. The weird flowers on the
download page are gone. But the link to "Introduction to Functional
Programming Using Haskell" takes me to the publisher page for the textbook
"Aqueous Environmental Geochemistry".

------
mimog
I like how it says "Rock-Solid Ecosystem", yet I have had the exact opposite
experience trying to install even the most basic things with Cabal. I still
can't get the Sublime text haskell plugin to work due to a dependency that
fails to compile.

~~~
rhizome31
I had a similar experience with Cabal. On one computer I haven't been able to
install Yesod whereas on another one, it finally worked after I had wiped my
~/.cabal. It gave me the impression that Cabal's dependency resolution
mechanism is still a bit britle.

Also I found that installing stuff through Cabal was pretty slow. It's
probably partly because Haskell libraries tend to be kept narrow in scope so
it's necessary to install a lot of small packages to get a piece of
functionality (take for instance the dependency list of Aeson, which seems to
be the recommended choice for working with JSON :
[http://hackage.haskell.org/package/aeson](http://hackage.haskell.org/package/aeson)
). Another reason is that Cabal compiles Haskell code into native code.

------
wtetzner
The site feels too flashy, and the giant photo feels distracting. It would be
nice if it felt "cleaner." As it is, I feel like a newcomer would find it
somewhat overwhelming visually.

I think something nice and simple like Rust's homepage[1] would be nice. Or
maybe something like Racket's homepage[2].

[1] [http://www.rust-lang.org/](http://www.rust-lang.org/) [2] [http://racket-
lang.org/](http://racket-lang.org/)

------
tieTYT
Wow I've gotta say, this looks great.

Something that bugs me is I couldn't copy the code in the upper right to the
code "try it" section. I haven't used haskell for 6-12 months, so I'm not sure
what I'm doing wrong.

Here's a screenshot: [http://imgur.com/N2SdFVq](http://imgur.com/N2SdFVq)

Regardless of _how_ to fix this, I think something should be changed so this
can't be someone's first impression.

~~~
codygman
It doesn't seem to support function declaration.

~~~
ingenter
You can use function declaration in the same line it is used.

`let { f x = x ^ 2 } in f 2`

------
tmslnz
Typo, missing _to_

> You shouldn't have rewrite half your code base when it's time to scale.

------
protez
I love Haskell and OCaml, and other functional languages. However, no matter
how intelligent and higher-level functional language becomes, I don't think
they can replace procedural language, especially for time-based programmings,
such as user interface effects, animations, or network-dependent operations.
Some features are inherently procedural by their nature, and functional
language are not functional for describing them.

------
progman
Many people know C++ and Java but have no sense for functional programming. It
would help them to read equivalent known code to compare it with Haskell.

For instance FP Complete's Introduction to Haskell presents some ugly Java
code which can be written in two elegant lines in Haskell (video around 03:25
min).

[http://www.youtube.com/watch?v=Fqi0Xu2Enaw](http://www.youtube.com/watch?v=Fqi0Xu2Enaw)

~~~
sparkie
This gets brought up often, but side-by-side comparisons don't really work,
because the languages are too different for them to be meaningful for anything
but trivial expressions. To really understand Haskell, you need to somewhat
_unlearn_ Java - or at least, stop thinking in it (in terms of objects, state
and method calling).

I think a good approach to thinking differently is to look how data structures
are done - most programmers recognize arrays, lists, stacks and queues, but
might be confused as to how you would implement such thing without side
effects. A great resource to explain this is Okasaki's Purely Functional Data
Structures[1], although it doesn't use Haskell at all, the ideas are relevant,
and you can work through all of the examples implementing Haskell equivalents.

[1]:[https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf](https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf)

------
rcarmo
Scores high on layout, not so much on usability (I, too, took a while to
realize there was a live REPL on the page) or readability.

(I'm one of those people who tried to learn Haskell a couple of times but
lacked use/time to really get to grips with it, so I can actually parse some
of it, but the samples ought to be simpler.)

------
moron4hire
The very first example I see, the infinite sequence of primes, seems to
indicate it is Eratosthenes' Sieve, but it is not.
[http://www.cs.hmc.edu/~oneill/papers/Sieve-
JFP.pdf](http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf)

In fact, the correct implementation, with some discussion of the bad
performance characteristics of the example on the front page, is in your own
wiki:
[http://www.haskell.org/haskellwiki/Prime_numbers#Sieve_of_Er...](http://www.haskell.org/haskellwiki/Prime_numbers#Sieve_of_Eratosthenes)

Reading further, it looks like it is the correct implementation of "Turner's
Sieve", but I don't think (though I may be wrong) that I'm in the minority
that sees "prime" and "sieve" and thinks "Eratosthenes".

------
weitzj
The View Examples link seems not to work on iOS 5 with an iPad 3

~~~
sampo
Neither on Firefox (default settings) on Ubuntu.

------
dmytrish
"Try haskell expression here" \+ lessons is very nice.

Just a little nitpick:

    
    
        λ map (+1) [1..5]
        can't find file: Imports.hs
        λ map (+ 1) [1..5]
        [2,3,4,5,6]:: (Enum b, Num b) => [b]
    

though the first expression is what suggested in lesson 4.

Edit: looks like some random bug.

~~~
msl09
yep, you are not the only one that had that problem

λ foldr (:) [] [1,2,3]

:: Num a => [a]

λ foldr (:) [] [1,2,3]

[1,2,3] :: Num a => [a]

~~~
fleitz
I had similar issues with the first expression, sometimes when executing a new
expression I also had to type it twice to get the answer.

------
pepper__chico
I'm in the process of finishing LYAH, and I'm also following CIS 194 which is
available online
([http://www.seas.upenn.edu/~cis194/](http://www.seas.upenn.edu/~cis194/),
[https://docs.google.com/file/d/0B0_mzHzbl3GbNXBWMVZPVGNtX3M](https://docs.google.com/file/d/0B0_mzHzbl3GbNXBWMVZPVGNtX3M)).
I've learned about it from
[https://github.com/bitemyapp/learnhaskell](https://github.com/bitemyapp/learnhaskell).

I think CIS 194 would be nice to be added in the book listing section? It's a
great course with exercises and at the same time refer to chapters of both
LYAH and RWH.

------
robinhoodexe
Nice, I like it. Now, to actually learn the language...

~~~
biscarch
This will help:
[https://github.com/bitemyapp/learnhaskell](https://github.com/bitemyapp/learnhaskell)

------
Folcon
Just trying out the tutorial: there may be an error on step 11.

followed the instruction to type out 'a' : [] and got:

λ 'a' : [] can't find file: Imports.hs

It worked when I clicked on the command, but that may not be obvious to a new
user.

λ 'a' : [] "a":: [Char]

------
teamonkey
Lovely page, but that primes example is going to put off more people than it
attracts, IMO. If you're not familiar with Haskell, or functional programming
in general, the syntax and concepts shown there would appear alien and obtuse.

------
pka
I started doing a redesign some time ago, but never finished it [1].

[https://dl.dropboxusercontent.com/u/30225560/poc-
haskell.png](https://dl.dropboxusercontent.com/u/30225560/poc-haskell.png)

------
mark_l_watson
I like the look. A question: I have always used the "The Haskell Platform"
download page and installer. The new download page looks like it is just
Haskell, cabal, and default libraries.

I am running ghc version 7.6.3 and cabal version 1.16.0.2.

Haskell experts: should I do a fresh install? (I am on OS X and Ubuntu).

Also, shameless plug: I blogged earlier today about using Haskell to access
OpenCalais and the DBPedia SPARQL endpoint:
[http://blog.markwatson.com/2014/07/some-haskell-hacks-
sparql...](http://blog.markwatson.com/2014/07/some-haskell-hacks-sparql-
queries-to.html)

~~~
jonsterling
If you're on OS X or Linux, you should not use the Haskell Platform. It's a
whole lot of pain for literally no gain...

~~~
mark_l_watson
Thanks Jon, I appreciate the advice. I am re-installing from haskell.org right
now.

------
Guthur
Natural, declarative, statically typed code.

Not sure how that first adjective applies.

~~~
jsmeaton
Looks like you're being downvoted, but I have to agree with you, especially
given some of the examples right at the top.

    
    
      foldr (:) [] [1,2,3] 
    

There is absolutely nothing natural about that line of code unless you happen
to already have some background. I executed that in the sandbox and got:

    
    
      [1,2,3]:: Num a => [a]
    

And I _still_ don't know what was achieved.

~~~
daffodil2
For a function f and a value x,

    
    
        foldr f x [a,b,c]
    

gets turned into

    
    
        f(a, f(b, f(c, x)))
    

'(:)' is list concatenation, so the result is

    
    
        1 : (2 : (3 : []))
    

(Here we are writing list concatenation in infix notation, rather than the
customary prefix notation). '[1,2,3]' is shorthand for 1 : (2 : (3: [])) in
Haskell.

~~~
jsmeaton
Thanks, I appreciate the walk through. So it's essentially just copying an
array (in this particular example). I'd still argue that the syntax is not
_natural_ \- since you have to have specific knowledge of the operator and the
function.

~~~
tel
Syntactic naturality seems like it's mostly a function of familiarity. That
said, the example has, for a lot of mathematical reasons, a great deal of
semantic naturality.

It's far from immediately obvious, but `foldr (:) []` is _the_ way to copy
singly-linked lists. In particular, if you look at a linked list as a
degenerate tree then what `foldr f z` does is replace all of the nodes with
`f` and the single leaf with `z`. Since cons, i.e. (:), creates a node and
nil, i.e. [], is that single leaf then `foldr (:) []` is a very natural way to
do nothing at all.

So it's kind of the most boring interesting example imaginable.

------
codygman
Whoa, the change happened! My girlfriend and I both think it looks awesome :)

Anyone know if there are plans to add the interactive/javascript examples as
well?

EDIT: Had noscript on, everything looks great.

------
euphemize
Awesome new look!

I sort of have a thing for commas:

    
    
        An advanced purely-functional programming language
    
        An advanced, purely-functional programming language
    

Much better, no?

~~~
dragonwriter
Depends on the intended meaning -- if it is that Haskell is advanced _among_
purely-functional programming languages, rather than both advanced and purely-
functional among programming languages, then the former is far better.

------
X4
Looks really good, but as others noted, the examples should really work `as
is` within the REPL. Also I think wikipedia has better example code. Everybody
knows fibonacci and can compare it.

Please add a nice Haskell facts and features tab, like: Appeared in 1990; 24
years ago More facts and features on:
[http://en.wikipedia.org/wiki/Haskell_(programming_language)](http://en.wikipedia.org/wiki/Haskell_\(programming_language\))

------
Camillo
The downloads page is a bit too deemphasized; the big, bright Download button
in the old page was a good call to action. However, I am really glad to see
that the downloads page no longer recommends the Haskell Platform for OS X or
Linux.

I wish there were better free book recommendations on the Documentation page.
LYAH's style is obnoxious, and RWH has gotten quite long in the tooth.

~~~
mrspeaker
I agree about the download page being too subtle: I _really_ love this new
redesign - the old site was impossible to figure out what I was supposed to do
or what was going on or what the hell "cabal" was. This new site is clean and
clear: but still missing a nice big call to action (besides the live coding
part).

Once you've looked at the live coding, the next thing is "community" which is
great for docs, but not so great for "getting up and running" \- which was
also hard to figure out on the old site. I'd prefer to be lead from the live
coding to clear instructions how to get Haskell running on my system.

But, again - I love this redesign... great work!

------
denibertovic
I like the new homepage. One little nit-pick, I actually find the quicksort
example a better candidate (instead of the sieve one). I think it highlights
the expressiveness of the language a lot, and everybody implemented quicksort
in some other language at one point, so they can compare.

------
basicallydan
I used to hate Haskell at University, until the final couple of weeks of the
module when I started to "get" it. After that, exams and dissertation (which
was in Python) got on top of me and I never revisited it. Now, coming back to
it I am starting to remember the fun I had :)

------
jammmuel
I dislike this. Where is the 'call for me to do something'? Why are there
blurred people on an escalator(?). Don't make me pick between concise and
reliable. I'm more than willing to distill your messaging if it would help in
any way. If only as an alternative.

~~~
gipp
> Don't make me pick between concise and reliable.

You missed the tongue-in-cheek, there. "Concise and Reliable: Pick _Two_."

And those people are in a lecture hall. Under "Open-source community effort."

------
eghri
Excellent! This is a big improvement. There seem to be some bugs with the "try
it now" terminal, but it was easy enough that I actually gave Haskell a try
after many years. It's got me interested enough to actually install it and
start hacking away!

------
rcconf
I find the disappearance of the Haskell text and logo in the navigation bar to
be really strange. It feels like I'm going to a completely different website
every time I click anything on the menu.

I think it should always stay there, or something else should be done
entirely.

------
anoxic
Just a nitpick: Why don't you stay consistent and use Open Sans for all the
main text and the logotype at the top. Having "Haskell" in Ubuntu when the
rest of the site is not stylized like that looks a little silly.

------
majika
The "Try It" section doesn't load without cookies/localStorage enabled. Having
run-time state should be fine for tracking where someone is up to on the
tutorial; persistent state shouldn't be necessary.

------
chewxy
I don't quite like this. The old one had front page links to the haskell wiki.
This design is really information undense. Also, links to Hoogle and packages
would be fantastic in the front page

------
72deluxe
It's pretty! BUT! I get the feeling that I am viewing websites through a post
box slot. This seems to be the trend with currently fashionable sites, with
the wall to wall slot appearance.

------
new_test
Off-topic: I want to learn a functional programming language, and I was
thinking to go with Scheme (because, you know, SICP...) Would there be any
advantage for me to go with Haskell instead?

~~~
thinkpad20
Scheme and Haskell are very different languages. Both are functional, but
that's about where the similarities end. Scheme is impure, haskell is pure;
scheme is strict, haskell lazy; scheme is dynamically typed, haskell static;
all functions in scheme are variadic, all in Haskell are unary; etc. So it
depends on what you're looking for, and what you're trying to use it to do.
That said, here are some advantages of Haskell:

1) Speed. Haskell binaries are highly optimized and tend to be very fast.

2) Correctness. Haskell's type system is far more advanced than any other
language with as much or more usage, and is very good at preventing runtime
errors. (and can go a long way to preventing logic errors). Also, its purity
prevents huge classes of bugs.

3) Interesting: Haskell introduces a lot of new concepts which can really open
up your understanding of computer science. It's a lot of fun.

4) Forward-looking: many of the ideas introduced or popularized by Haskell,
such as pattern-matching, type classes, no null pointers, etc, are manifesting
themselves in the new languages these days (such as Rust and Swift). Haskell
itself is also (slowly) making its way into industry. Learning Haskell, in
some ways, exposes you to the "next generation" of languages and programming
techniques. I'm not sure the same can be said of Scheme, which tends to be
used pedagogically more than as a means to push the envelope.

Then again, I know Haskell a lot better than I know Scheme, so maybe I'm
biased. But at least, it gives you something to think about.

~~~
new_test
Thanks.

By training I am not a computer scientist, but an applied mathematician, so it
is a little difficult for me to make judgement calls on things like type
system, lazy evaluation, unary/variadic (don't even know what that means). I
am interested in AI (machine learning) and statistical inference. I was
looking at Lisp/Scheme because I know that AI needs gave birth to Lisp. Plus
you have newer things like Church[1] that extends Scheme to deal with
probabilistic models.

[1][http://projects.csail.mit.edu/church/wiki/Church](http://projects.csail.mit.edu/church/wiki/Church)

------
asgard1024
I think Haskell deserves a concise, functional homepage. Ideally, without any
side effects (like animation). Every URL should always return either the same
content, or an appropriate monad.

------
sreya
I really, really want to get into Haskell and functional programming in
general, but I have no idea what sort of project to build with it. Anyone have
any good suggestion?

~~~
ibotty
haskell can be used for pretty much everything (even hard realtime with a code
generating dsl called atom), so just think about what you enjoy/like and maybe
ask before for pointers to libraries you might use with that task.

if there is anything you like but is algorithmically challenging, all the
better. it's very nice to express math in haskell.

------
tree_of_item
Titles for each of the videos would have been nice, just so I could get an
idea of what I'm about to click on.

------
elwell
An important addition to the Documentation section might be something about
using Haskell for the web.

------
wcauchois
If the interpreter isn't going to work on mobile, you should hide it.

------
mike_ivanov
This page would seriously benefit from a few random kitten pictures.

------
cpplinuxdude
"You shouldn't have rewrite half your code base".

------
slashdotaccount
Ugh, doesn't use progressive enhancement:

[https://en.wikipedia.org/wiki/Progressive_enhancement](https://en.wikipedia.org/wiki/Progressive_enhancement)

~~~
VMG
How would the REPL look like with progressive enhancement?

 _" Thanks submitting a Haskell line! You're being redirected to the output of
the evaluation. If you're not being redirected automatically, please click
_here_"_

------
doctorKrieger
looks kinda generic but it's quite nice.

------
rhapsodyv
Much better! I hate the red links...

------
cweathe2
How did it know I was 28??? ;-)

------
pyed
This design is beautiful and elegant, just like Haskell.

------
PeterWhittaker
Wow, nice.

------
IBCNU
sexy

------
wfbarks
not at all surprised that the first code sample is A) Cryptic as hell and B)
Something I basically never need to do when developing an app

------
skratlo
Please, can anyone come up with something original? Or at least usable.

