Types

Type annotations

  • Every expression can be annotated with a type signature
  • Types can be generic and have type variables

Count with type signature

In [ ]:
count' :: [a] -> Int -> Int
count' [] result = result
count' (first:rest) result = count' rest (result + 1)
In [ ]:
count :: [a] -> Int
count list = count' list 0

Laziness

Nonstrict evaluation

  • Expressions are not evaluated until their value is needed
  • Haskell implements this using lazy evaluation

Laziness

Infinite lists

In [ ]:
allNumbersStartingAt n = n : allNumbersStartingAt (n+1)
take 5 (allNumbersStartingAt 0)

{.haskell .fragment} → [0,1,2,3,4]

Repeat a list endlessly

In [ ]:
take 11 (cycle ['S','O','S', '-'])

{.haskell .fragment} → "SOS-SOS-SOS"


Partial function application

Infix functions (operators)

  • Can also be partially applied
  • Just wrap them in parenthesis and omit one operand

Example /

In [ ]:
divideByTen :: Fractional a => a -> a
divideByTen = (/ 10)

Example elem

In [ ]:
isUpperCase :: Char -> Bool
isUpperCase = (`elem` ['A' .. 'Z'])

Functions as arguments

Example: Do something twice

In [ ]:
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
  • First parameter is a function of type (a -> a)
  • Second parameter is a value of type a

Things to do twice

In [ ]:
applyTwice (+3) 10
applyTwice ("Hello, " ++) "who is there?"
applyTwice (3:) [1]

zipWith' implementation

Recursive function with pattern matching

In [ ]:
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f [] bs = []
zipWith' f as [] = []
zipWith' f (a:as) (b:bs) = f a b : zipWith' f as bs

zipWith' applications

Guess what the results are

In [ ]:
zipWith' (+) [1, 2, 3] [1, 2, 3]
zipWith' (*) (replicate 4 3) [1..]
zipWith' max [3,7,2] [4,1,6]
zipWith' (++) ["James T. ", "", "Nyota "] ["Kirk", "Spock", "Uhura"]
In [ ]:
fibs = 0 : 1 : zipWith' (+) fibs (tail fibs)

Assignment 1

Fibonacci number

Canonical Haskell implementation

In [ ]:
fibs :: [Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

Mapping

Function map

In [ ]:
map :: (a -> b) -> [a] -> [b]  
map _ [] = []  
map f (x:xs) = f x : map f xs
  • Take a function
  • Apply to every element of the list
  • Collect the results in a list

Mapping

Examples

In [ ]:
map ("Beam me up, " ++) ["Kirk", "Spock", "Scotty"]
map (replicate 3) [1, 2, 3]
map fst [('A', 'B'), ('C', 'D'), ('E', 'F')]
map snd [('A', 'B'), ('C', 'D'), ('E', 'F')]

Filtering

Function filter

In [ ]:
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' p (x:xs)
  | p x = x : filter' p xs
  | otherwise = filter' p xs
  • Take a predicate
  • Apply to each element of the list
  • Assemble new list of elements that satisfy the predicate

Filtering

Examples

In [ ]:
filter (>3) [1,5,3,2,1,6,4,3,2,1]
filter even [1,5,3,2,1,6,4,3,2,1]
filter (`elem` ['a'..'z']) "Beam me up, Scotty!"
filter (`elem` ['A'..'Z']) "Beam me up, Scotty!"