Wow, how did my Haskell tutorial get to the HN front page out of nowhere? :-)
If you like my stuff, keep an eye out for my new Bitcoin book, which will be coming out this fall. I've been slaving over the artwork for months, it should be a beautiful book! The working title is "Bitcoins for the Befuddled".
To be clear, I haven't finished the book yet, but I made it through the first eleven chapters (~230 pages) so I think I've gone through enough material to render a reasonable opinion. With that disclaimer out of the way...
I love that the author chose to expose readers to core, foundational concepts through example programs that were continually improved instead of using lots of throwaway one-off examples.
Put differently, the author managed to ensure that readers that diligently followed through from beginning to end would gain a real sense of progression as they went through the material.
The only complaint I really have so far is Chapter 11 -- but that's not really the author's fault; that's just the terrifyingly mind-numbing formatting functionality (Common?) Lisp offers.
Seconding the recommendation for Land of Lisp. It's fun, well-written, and thorough. And has the most fun art I've seen in a programming manual.
I read five great books on Common Lisp.
Intro level: ANSI Common Lisp (by our very own PG), Practical Common Lisp, and Land of Lisp. Can't go wrong with any of them, but LoL has art and humor.
Advanced level: On Lisp (again, PG), and Let Over Lambda (a bit rougher around the edges, opinionated, but full of clever programming tricks).
Read it. How can you not read a book with such a front cover? And it has examples you really want to play with (literally), not 10000 kinds of "hello fibonacci".
> In Haskell, this type of integer can't get bigger than 2^31...
It's platform-dependent
h> finiteBitSize (0 :: Int)
64
> We could have used the type Integer instead- This type of integer grows "magically" and can hold any sized integer, no matter how big... but it's slower, so we used Int instead, since our numbers will never get that big.
I don't know why anyone would use the Integral typeclass over just Int or Integer in a simple program like this, but you wouldn't need Num in addition to Integral, every instance of Integral must also be an instance of Real, and instances of Real must be instances of Num.
Picnicmob was a really clever idea. I think I remember that it got cancelled though, which was unfortunate.
I like the tutorial though. I'd be willing to bet it's his style and work that inspired the "Learn you a..." books. The Haskell one is great, and so is the Erlang one.
I like the tutorial very much! Thank you! And I like the final words, which I think brings to the point the whole discussion about Haskell vs. Imperative languages:
[..] Because the physical world changes only slightly
from moment to moment, it means that languages that
can comfortably mutate large data structures in targeted
ways will always have a role to play in real-world
software- The "real world" usually just doesn't work the
way Haskell, and other functional languages would prefer
it did: Haskell preferred that at every moment in time, a
"new universe" would look at the "old universe" and would
rebuild itself, from scratch, from what it saw in the
past, with radical changes happening all the time.
Despite its many advantages, I humbly suggest, therefore,
that in the future there will continue to be a rift
between the "imperative" and "functional" camps of
programming, until someone comes up with a truly robust
way of uniting these two camps- And I think that some
profound programming discoveries still need to be made in
the future before this problem is really resolved- I get
the feeling it's just not good enough to wave at the
problem and say "Monads".
It doesn't seem to be outdated. I guess you probably didn't follow correctly the instructions (or maybe they aren't explained well). The extra code given in the second example goes just after the code in the first example, starting with the same indentation. Something like:
main = do
putStr "Hello World! Let's have a picnic! \n"
people_text <- readFile "people.txt"
-- ... the rest
This confused me when I was learning Haskell as well. The way I understand it is that regex-base defines a base-line interface -- such as the context-aware =~ function -- that all of the other packages implement, which is why they're known as 'backends' (e.g. regex-tdfa, regex-pcre, etc.).
In newer versions of GHC (> 6.6), the backends re-export this interface so that you just need to import the backend. regex-tdfa is the backend that I've used myself, mainly because I saw it used in other packages (Hakyll).
[1] - Lines of active code only, not counting optional function signatures. Intermediate debug output lines excluded. May cause eye irritation if viewed for prolonged periods of time. Speak to your physician to find out if this tutorial is the best treatment option for you.
If you like my stuff, keep an eye out for my new Bitcoin book, which will be coming out this fall. I've been slaving over the artwork for months, it should be a beautiful book! The working title is "Bitcoins for the Befuddled".