Archives

Creative Commons License
This blog is licensed under a Creative Commons License.

Journey into Haskell, part 6

| 6 Comments | No TrackBacks

Create a list of primes “as you go”, considering a number prime if it can’t be divided by any number already considered prime.

However, although my straightforward solution worked on discrete ranges, it couldn’t yield a single prime when called on an infinite range – something I’m completely unused to from other languages, except for some experience with the SERIES library in Common Lisp.

An incomplete solution

Looking similar to something I might have written in Lisp, I came up with this answer:

primes = reverse . foldl fn []
    where fn acc n
              | n `dividesBy` acc = acc
              | otherwise         = (n:acc)
          dividesBy x (y:ys)
              | y == 1         = False
              | x `mod` y == 0 = True
              | otherwise      = dividesBy x ys
          dividesBy x [] = False

But when I suggested this on #haskell, someone pointed out that you can’t reverse an infinite list. That’s when a light-bulb turned on: I hadn’t learned to think in infinites yet. Although my function worked fine for discrete ranges, like [1..100], it crashed on [1..].

So back to the drawing board, later to come up with this infinite-friendly version:

primes :: [Int] -> [Int]
primes = fn []
    where fn _ [] = []
          fn acc (y:ys)
              | y `dividesBy` acc = fn acc ys
              | otherwise         = y : fn (y:acc) ys

          dividesBy _ [] = False
          dividesBy x (y:ys)
              | y == 1         = False
              | x `mod` y == 0 = True
              | otherwise      = dividesBy x ys

Here the accumulator grows for each prime found, but returns results in order whose value can be calculated as needed. This time when I put primes [1..] into GHCi it printed out prime numbers immediately, but visibly slowed as the accumulator grew larger.

No TrackBacks

TrackBack URL: http://www.newartisans.com/mt/mt-tb.cgi/2552

6 Comments

Better refer to the related SICP section[1] next time.

[1] http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-24.html#%sec3.5.2

Wow that’s really easy to read.

Hi John,

First, I want to say I have enjoyed reading your writing for several years.

You strike me as someone who would want to figure this all out on your own, but here is a link to a paper you may find interesting. The paper helped me learn some Haskell concepts better, and it explains a very nice prime number algorithm.

http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

Dave

Thanks, Dave, I will definitely check that out. And although I do like to figure things out on my own at first, I also like to see what other minds have found, because often it leads down trails I never imagined.

-- So complex!  Lazy birecursion,

primes = 2:filter isPrime [3..]
isPrime i = all ((/=0) . mod i) $ takeWhile ((<=i) . (^2)) primes

Very cool. Now I just have to study it!

Leave a comment

About this Entry

This page contains a single entry by John Wiegley published on March 26, 2009 8:00 AM.

Journey into Haskell, part 5 was the previous entry in this blog.

Response to PG's "How to Do Philosophy" is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Recent Comments

  • yoman: “Barfin”? “Slurping”? “Slime” “Hunchentoot” ??? What in the T.F. world read more
  • Bjorn Tipling: Why would you add instructions for installing an editor when read more
  • Mark Aufflick: sudo port install sbcl +threads If you previously installed sbcl read more
  • Alexander Lehmann: Thank. You. So. Much. – Clisp caused a lot of read more
  • Vetle: Btw, to get support for threading in SBCL, you have read more
  • ifade: I tried the same and get the same answer, but read more
  • Martial Boniou: Hi, I tried to install slime with MacPorts and I read more
OpenID accepted here Learn more about OpenID
Powered by Movable Type 4.25