So I decided to learn me some Haskell.
The first thing I did was to get a working build of the GHC (Glasgow Haskell Compiler) by following the appropriate links at the official Haskell site. Next, I found some learning materials, including Real-World Haskell, Learn You a Haskell for Great Good, Haskell Wikibook, Planet Haskell, and Erik Meijer's excellent Channel 9 series. (The latter is worth watching for the shirts alone!)
And then, a couple of days ago, I got to work learning. And so far…
…so good. This is a really fun language, and fairly easy to learn if you already have some experience in F#. At least, knowing F# gets you past the initial strangeness of concepts like currying, pattern matching, etc. In fact, knowing F# is a tiny bit of an impediment because the syntax is so similar, the differences are difficult to remember. But on balance, knowing F# has helped a bunch. The two languages aren’t exactly siblings, but they are cousins, and I think learning the more formal environment of Haskell will help me with the more pragmatic environment of F#.
In order to illustrate the two together, below I present “A tiny corner of Lisp…” in both F# and in Haskell. This being a little fragment of Lisp functionality coded as identically as possible in the two languages. As always, the code and information here are presented "as-is" and without warranty or implied fitness of any kind; use at your own risk. (And since I don’t yet have anything that can syntax highlight Haskell, I deliberately did not syntax highlight the F#.)
// A tiny corner of Lisp in F#.
type Node =
| Atom of string
| Cons of Node*Node
let car = function
| Cons(h,_) -> h
| _ -> failwith "Invalid 'car' target."
let cdr = function
| Cons(_,t) -> t
| _ -> failwith "Invalid 'cdr' target."
let rec append nCar nCdr =
match nCar with
| Cons(h,t) -> Cons(h, append t nCdr)
| Nil -> nCdr
| _ -> failwith "Invalid 'append' target(s)."
let a0 = Atom "a" // a
let c0 = Cons(a0,(Cons((Atom "b"),Nil))) // (a b)
let c1 = append c0 c0 // (a b a b)
let c2 = append c1 a0 // (a b a b . a)
-- A tiny corner of Lisp in Haskell.
data Node = Atom String
| Cons Node Node
car :: Node -> Node
car (Cons h _) = h
car _ = error "Invalid 'car' target."
cdr :: Node -> Node
cdr (Cons _ t) = t
cdr _ = error "Invalid 'cdr' target."
append :: Node -> Node -> Node
append (Cons h t) nCdr = (Cons h (append t nCdr))
append Nil nCdr = nCdr
append _ _ = error "Invalid 'append' target(s)."
a0 = Atom "a" -- a
c0 = Cons a0 (Cons (Atom "b") Nil) -- (a b)
c1 = append c0 c0 -- (a b a b)
c2 = append c1 a0 -- (a b a b . a)
So get out there and learn you a Haskell for great good!