Hello Haskell

We will ease into Haskell by com­par­ing it to our trusty steed OCaml. You might ask “why are we both­er­ing to learn another func­tional lan­guage?”If your ques­tion is more like “why func­tional pro­gram­ming at all?” you might want to watch John Hughes’ talk on the sub­ject, or read his famous paper “Why Func­tional Pro­gram­ming Mat­ters.” First, let me admit that I love OCaml. It’s a great lan­guage, but Haskell is more widely used and is endowed with many use­ful fea­tures. This is a dou­ble-edged sword. For exam­ple, Haskell’s more advanced type sys­tem yields type errors that are much more dif­fi­cult to under­stand than OCaml’s. But, we will find the lan­guage’s com­plex­ity allows us to write sim­ple and ele­gant code. Pro­grams that could not have been writ­ten as nicely in OCaml.N.b., other opin­ions exist, but this is mine.

I will freely admit, this is the most dull lec­ture of the semes­ter. How­ever, we have to start some­where. It’ll get bet­ter next week. I promise.

Installing and Running

All you’ll need is a text edi­tor and a Haskell com­piler. The most com­monly used com­piler is GHC, the Glas­gow Haskell Com­piler. You can install this, and other use­ful tools, with the Haskell Plat­form. Put the fol­low­ing code in hello.hs.

main = put­Str­Ln "Hello Haskell"

Run­ning ghc hello.hs will pro­duce an exe­cutable a.out file. Run­ning this will yield “Hello Haskell” as expected. Haskell also has a top-level inter­face called ghci. Enter the fol­low­ing in GHCi:

put­Str­Ln "Hello Haskell"

This should print “Hello Haskell” as before. You can load a Haskell file from within GHCi by using the :l myfile com­mand. This will load func­tion def­i­n­i­tions from myfile.hs. You can quit GHCi with :q.

Comparing OCaml and Haskell

Let’s see some code. On the left I will put a sim­ple OCaml frag­ment and on the right a cor­re­spond­ing Haskell imple­men­ta­tion. Take note of the sim­i­lar­i­ties and dif­fer­ences.

OCaml

Haskell

(* A sin­gle line com­ment. *)
(* A mul­ti­ple line com­ment.
   Can say even more. *)
-- A sin­gle line com­ment.
{- A mul­ti­ple line com­ment.
   Can say even more. -}
1
1
1 + 1
1 + 1
true
True
not false
not False
1 = 1
1 == 1
1 <> 1
1 /= 1
"Hello " ^ "world"
"Hello " ++ "world"
[1; 2; 3; 4]
[1, 2, 3, 4]
[1; 2] @ [3; 4]
[1, 2] ++ [3, 4]
1 :: [2; 3; 4]
1 : [2, 3, 4]
('a', 1)
('a', 1)
let add x y = x + y
add x y = x + y
if 1 = 1 then 2 else 3
if 1 == 1 then 2 else 3
let cal­cu­late x =
  let a = x * 2 in
  let b = x - 1 in
  a * b
cal­cu­late x =
  let a = x * 2
      b = x - 1
  in a * b
let rec fib n =
  if n == 1 || n == 2 then n
  else fib (n - 1) + fib (n - 2)
fib 1 = 1
fib 2 = 2
fib x = fib (x - 1) + fib (x - 2)
let rec my_map f xs =
  match xs with
  | [] -> []
  | x :: xt -> (f x) :: (my_map f xt)

my_map (fun x -> x * 2) [1; 2; 3]
my­Map _ [] = []
my­Map f (x : xt) = (f x) : (my­Map f xt)

my­Map (\x -> x * 2) [1, 2, 3]
let rec my_fold_left f acc xs =
  match xs with
  | [] -> acc
  | x :: xt -> my_fold_left f (f acc x) xt
my­Fold­Left f acc xs =
  case xs of
    [] -> acc
    x : xt -> my­Fold­Left f (f acc x) xt
type cur­rency =
  | USD of float
  | Euro of float
data Cur­rency = USD Float | Euro Float

What did you notice? Here are a cou­ple of inter­est­ing points.

These are just some high­lights, there are plenty more dif­fer­ences you’ll come across in due time.

Getting Help

Let’s say you have a ques­tion about a Haskell func­tion. Maybe you’ve for­got­ten the order of argu­ments to one of the fold func­tions.Yes, it’s a dif­fer­ent argu­ment order from OCaml. Yes, it’s infu­ri­at­ing. Your best resource is prob­a­bly Hoogle, the doc­u­men­ta­tion search engine.

For more gen­eral ques­tions, con­sult some of the addi­tional read­ing.

Additional Reading

Here are a cou­ple of good ref­er­ences for basic Haskell. I still con­sult with these reg­u­larly to refresh myself on syn­tax.