Introduction To Haskell

Lecture 4


Using These Slides

Every slide has a secret note.

  • On Chrome: press F12, then click Console
  • On IE: press F12, then click Console
  • On Firefox: Ctrl+Shift+k

Shortcut Keys:

, PgDn, n, j next slide
, PgUp, p, k prev slide
Esc enables ctrl+f globally


Haskell is

  • Purely functional
  • Statically typed
  • Lazy

Data looks like

  • Bool
  • Int
  • Char
  • ...

Lists and Tuples are useful data structures




(1, "one")

More Review

Everything in Haskell has a Type

Here are some Type declarations.

These are your greatest weapons.

head :: [a] -> a -- gets the first element of a list

tail :: [a] -> [a] -- gets everything but the first element

last :: [a] -> a -- gets the last element of a list

init :: [a] -> [a] -- gets everything but the last element

(++) :: [a] -> [a] -> [a] -- concatenates two lists together

(:) :: a -> [a] -> [a] -- prepends an element to a list

fst  :: (a,b) -> a -- gets the first element of a tuple

snd  :: (a,b) -> b -- gets the second element of a tuple

Review of Homework 3

Implement a Caesar Cipher

-- This example uses 'succ' to get next letter

cipher :: String -> Int-> String
cipher "" n = ""
cipher str n = rotate (head str) n : cipher (tail str) n

rotate :: Char -> Int -> Char
rotate c 0 = c
rotate c n = rotate (next c) (n-1)

next :: Char -> Char
next c = if c=='z' then 'a' else succ c

Pattern Matching

A function can have multiple patterns

Almost like overloading methods in Java or C++

guess :: Int -> [Char]
guess 42 = "correct!"
guess x  = "wrong guess!"

Each pattern has the same type declaration

Pattern Matching

  • Patterns are matched in order, top-down

  • Only the first matched pattern is evaluated

  • The patterns must exhaust the entire domain

What's wrong with this code?

fib :: Int -> Int
fib n = fib(n-1) + fib(n-2)
fib 0 = 1
fib 1 = 1

The base case is never hit.

The first pattern eats up everything!

∞ loop

More Pattern Matching

You can even match lists using Construct

head (firstItem : everythingElse) = firstItem

tail (x:xs) = xs

More Pattern Matching

Write a function to detect if a list is a palindrome

isPal :: Eq a => [a] -> Bool

(clear answer) (show answer)

Pattern matching is powerful

We can define fst with pattern matching

fst :: (a,b) -> a
fst (x,y) = x

Try defining head with pattern matching

head :: [a] -> a

(clear answer) (show answer)

Wildcard in Pattern Matching

  • We can specify when a value is unused.

  • The "_" symbol is called a wildcard in Haskell.

  • This is how it's used:

    head (x:_)  = x
    tail (_:xs) = xs

Error Handling

When GHCi is angry, it produces error messages through the error function.

error :: [Char] -> a

The official implementation of head is

head             :: [a] -> a
head (x:_)       =  x
head []          =  error "Prelude.head: empty list"



  • Guards are clean if statements.

  • Just like with pattern matching, order matters.

  • A guard is introduced by the | symbol.

  • And it's followed by a Bool expression.

  • Then followed by the function body

    guessMyNumber x
                | x > 27    = "Too high!"
                | x < 27    = "Too low!"
                | otherwise = "Correct!"
    otherwise is just a fancy word for True


Guards are very powerful.

Anything done with pattern matching can be done with guards.

head' :: [a] -> a
head' xs
    | null xs   = error "list is empty"
    | otherwise = xs !! 0
!! is a function that gives an element at an index


These are not like your typical Java variables

In Java or C++, you can redefine variables:

x = 1;


x = 2;

Mathematically, this makes no sense.

It implies 1=2 Preposterous!


Haskell variables are immutable.

Once defined, they can't change.

They can be used with the let keyword.

slope (x1,y1) (x2,y2) = let dy = y2-y1
                            dx = x2-x1
                        in dy/dx

Or with the where keyword.

slope (x1,y1) (x2,y2) = dy/dx
                        where dy = y2-y1
                              dx = x2-x1


In Haskell, indentation matters.

Code which is part of some expression should be indented further in than the beginning of that expression *



Don't use tab. Use spaces ' '.


A Useful Tool

  1. Fill out this week's form.
  2. Convert between metric and imperial.

    convert :: (Double, [Char]) -> (Double, [Char])

    • m ↔ yd
    • L ↔ gal
    • kg ↔ lb
    Prelude> convert (1, "m")
    (1.09361, "yd")
    Prelude> convert (1, "L")
    (0.264172, "gal")
    Prelude> convert (1, "kg")
    (2.20462, "lb")