Lecture 4

#SyntaxSwag

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

Review

 Haskell is Purely functional Statically typed Lazy Data looks like Bool Int Char ...

Lists and Tuples are useful data structures

 List [1,2,3] Tuple (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
 A B C D

-- 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

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

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

• 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

Guards are very powerful.

Anything done with pattern matching can be done with guards.

head' :: [a] -> a
| null xs   = error "list is empty"
| otherwise = xs !! 0

!! is a function that gives an element at an index

Variables

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! Variables

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

Whitespace

In Haskell, indentation matters.

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

Level-1
Level-2
Level-3
Level-3
Level-3
Level-2
Level-3
Level-3

Level-1
Level-2
Level-2

Level-1

Don't use tab. Use spaces ' '.

Homework

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")