Lecture 4
#SyntaxSwag
F12
, then click ConsoleF12
, then click ConsoleCtrl+Shift+k
↓ , PgDn , n , j 
next slide 
↑ , PgUp , p , k 
prev slide 
Esc 
enables ctrl+f globally 
Haskell is

Data looks like

Lists and Tuples are useful data structures
List [1,2,3]

Tuple (1, "one")

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
 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) (n1)
next :: Char > Char
next c = if c=='z' then 'a' else succ c
 Importing a really useful library
 designed by Preetam C. Jinka
import Data.Char
cipher :: [Char] > Int > [Char]
cipher [] _ = []
cipher (s:ss) n = (rotate s n) : (cipher ss n)
rotate :: Char > Int > Char
rotate c 0 = c
rotate c n = int2letter ( mod ((letter2int c) + n) 26 )
letter2int c = ord c  97
int2letter n = chr (n + 97)
 Here's a oneline solution
 designed by James C. Sun
import Data.Char
cipher :: [Char] > Int > [Char]
cipher s n = map (\c > ([c..'z'] ++ ['a'..c]) !! mod n 26) s
 designed by Matthias pall Gissurarson
import Data.List
import Data.Maybe
alphabet:: [Char]
alphabet = cycle ['a'..'z']
rotate:: Int > Char > Char
rotate k a = alphabet !! (k + ( fromJust ( elemIndex a alphabet)))
cipher:: [Char] > Int > [Char]
cipher str k = map (rotate k) str
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
Patterns are matched in order, topdown
Only the first matched pattern is evaluated
The patterns must exhaust the entire domain
fib :: Int > Int
fib n = fib(n1) + fib(n2)
fib 0 = 1
fib 1 = 1
The base case is never hit.
The first pattern eats up everything!
∞ loopYou can even match lists using Construct
head (firstItem : everythingElse) = firstItem
tail (x:xs) = xs
Write a function to detect if a list is a palindrome
isPal :: Eq a => [a] > Bool
isPal :: Eq a => [a] > Bool
isPal [x] = True
isPal [x,y] = x == y
isPal (x:xs) = (x == (last xs)) && isPal (init xs)
(clear answer)
(show answer)
We can define fst
with pattern matching
fst :: (a,b) > a
fst (x,y) = x
Try defining head
with pattern matching
head :: [a] > a
head :: [a] > a
head (x:xs) = x
head [x] = x
head [] = error "empty list"
(clear answer)
(show answer)
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
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.
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 = y2y1
dx = x2x1
in dy/dx
Or with the where
keyword.
slope (x1,y1) (x2,y2) = dy/dx
where dy = y2y1
dx = x2x1
In Haskell, indentation matters.
Code which is part of some expression should be indented further in than the beginning of that expression*
Level1
Level2
Level3
Level3
Level3
Level2
Level3
Level3
Level1
Level2
Level2
Level1
Don't use tab. Use spaces '
'.
Convert between metric and imperial.
convert :: (Double, [Char]) > (Double, [Char])
Prelude> convert (1, "m")
(1.09361, "yd")
Prelude> convert (1, "L")
(0.264172, "gal")
Prelude> convert (1, "kg")
(2.20462, "lb")