haskell-infra / hl

Haskell web site (old -- see new repo at https://github.com/haskell-infra/www.haskell.org)
http://haskell.org/
BSD 3-Clause "New" or "Revised" License
158 stars 92 forks source link

The header code example #46

Open bluealert opened 9 years ago

bluealert commented 9 years ago
fibonacci 0 = 0
fibonacci 1 = 1
fibonacci n = fibonacci (n - 1) + fibonacci (n - 2)

why use this very inefficient solution? I think use the below solution is better ?

fibs = 1:1: zipWith (+) fibs (tail fibs)

may give new Haskell user very bad feel ?

chrisdone commented 9 years ago

The current example as of now is:

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

This is the original example I made and I've restored it. It's inefficient when you run it. But it's very efficient at its purpose, which is to demonstrate:

  1. where syntax,
  2. enumeration syntax,
  3. pattern matching,
  4. consing as an operator,
  5. list comprehensions,
  6. infix functions
  7. laziness

If you can make an alternative example which satisfies that many criteria for giving a "feel" of the language, please contribute it. I've added a title attribute to the text commenting to the same effect.

chrisdone commented 9 years ago

I will keep this issue open for future people to see.

bluealert commented 9 years ago

this example is very good. :+1: you forget to call the sieve function.

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

Although I cannot think of a better example right now, I believe this example is misleading. Melissa O'Neil wrote a good article on why: http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

You mention that the purpose of the example is to demonstrate, but then list six points on the syntactic construction, which are not essential to the real strength of Haskell. (I do agree upon your seventh point: laziness.) My concern is that this example will lead new Haskell users to believe that Haskell can be understandable or efficient, but never both. Actually, it might lead them to believe that Haskell cannot be efficient...

A minor(?) second concern is that this example cannot be entered in the "Try it" REPL directly below. See also this comment on this HN thread.

jwaldmann commented 9 years ago

"+1" to sebastianv89. This "primes" example is misleading, also for this reason: the subsection heading is "declarative and statically typed", but there are no (visible) types in this code snippet.

chrisdone commented 9 years ago

Although I cannot think of a better example right now, I believe this example is misleading. Melissa O'Neil wrote a good article on why: http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

People have been linking this since May last year. I'm aware of the paper. But the example cannot demonstrate anything semantic in a few lines, the point is to show what Haskell feels like on the surface. Nobody's going to actually go run the function.

sebastianv89 commented 9 years ago

At least call the supporting function something else than sieve, because it is not a sieve.

Also:

What is the point of demonstrating the power an elegance with an example that will (hopefully!) never appear in any real world code? Better to show how the language is still powerful and elegant when taking into account the edge cases and common optimizations.

Writing elegant non-real-world code is much easier (in any language!) than writing real code. src: https://news.ycombinator.com/item?id=9052869

gbaz commented 9 years ago

For what its worth, it is a sieve, absolutely! Just not the classic sieve, and not as efficient as that one.

cdupont commented 9 years ago

I have mitigated feelings on this example. The plus:

The minus:

Of course it's hard to find an example both powerful and beginner-accessible. IMO writing it the opposite way is a little bit clearer:

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

It's more chronological (defining sieve first), avoids where keyword and indentation tricks.

Also I would add a "what is this?" or "explain me" link explaining what it is (it's not clear to a beginner that this will generate a list of primes) and giving some explanation on how it works.

gbaz commented 9 years ago

A bigger real problem is that as per #87, you can't type it into the repl right below!

gbaz commented 9 years ago

So Ertugrul also suggests we change the name from sieve to trialDiv at the least. It seems like there's enough sentiment that we should do that.

chrisdone commented 9 years ago

Sure, why not.

gibiansky commented 9 years ago

Suggestion: instead of having a single bit of code there with no explanation, imitate the way Racket does this. They have a bit of code with < and > buttons to advance to the next bit of code or previous and they have an "explain" link to the top right of each one that pops up a modal window with an in-depth explanation of the code. I remember seeing this years ago and being hugely impressed by the presentation style, and it seems like it might fit well here.

Then we can have a variety of code snippets meant to show off different things; for example (just ideas):

What do people think of this? I think this would give a much more complete view of Haskell as a language and ecosystem. It's a non-trivial amount of work and honestly I don't know how much I can contribute (hopefully some, if people think this is worthwhile), but maybe it's the right way to present these code blocks.

chrisdone commented 9 years ago

@gibiansky that was in my original proposal but coming up with that content as you note requires time and thinking not yet spent by anyone yet.

gibiansky commented 9 years ago

@chrisdone Ah, makes sense. If there is some time in my life I will tackle this in the next several weeks, but no promises.

treblacy commented 9 years ago

I came here after I saw the discussion in haskell-cafe.

I submit these candidates:

-- all digit strings (infinite list, shorter lengths first)
digitals = [] : extend digitals
  where
    base = ['0' .. '3']
    extend dss = [ d : ds | ds <- dss, d <- base ]

-- but do you want to demo alphabetical infix?
digitals = [] : ['0' .. '3'] `prepend` digitals
  where prepend b dss = [ d : ds | ds <- dss, d <- b ]

-- or do you want to demo user-defined non-alphabetical?
digitals = [] : ['0' .. '3'] +> digitals
  where b +> dss = [ d : ds | ds <- dss, d <- b ]

P.S. http://cowbirdsinlove.com/43

maggy96 commented 9 years ago

What about quicksort? I think it's pretty impressive. Also it's general and I think everybody knows quicksort.