Recap, Quiz and Cheatsheet
Recap
Things you can use as patterns:
Int
andInteger
constants like(-1)
,0
,1
,2
, …Bool
valuesTrue
andFalse
Char
constants:'a'
,'b'
String
constants:"abc"
,""
Maybe
constructors:Nothing
,(Just x)
Either
constructors:(Left x)
,(Right y)
- The special
_
pattern which means “anything, I don’t care” - Combinations of these patterns, like for example
(Just 1)
- We’ll learn about other patterns, for example lists, in the next chapters.
Places where you can use patterns:
- Defining a function with equations:
f :: Bool -> Maybe Int -> Int
f False Nothing = 1
f False _ = 2
f True (Just i) = i
f True Nothing = 0
- In the
case of
expression:
case number of 0 -> "zero"
1 -> "one"
_ -> "not zero or one"
The only thing you really need pattern matching for is getting the value inside a Just
, Left
or Right
constructor. Here are two more examples of this:
-- getElement (Just i) gets the ith element (counting from zero) of a list, getElement Nothing gets the last element
getElement :: Maybe Int -> [a] -> a
getElement (Just i) xs = xs !! i
getElement Nothing xs = last xs
Prelude> getElement Nothing "hurray!"
'!'
Prelude> getElement (Just 3) [5,6,7,8,9]
8
direction :: Either Int Int -> String
direction (Left i) = "you should go left " ++ show i ++ " meters!"
direction (Right i) = "you should go right " ++ show i ++ " meters!"
Prelude> direction (Left 3)
"you should go left 3 meters!"
Prelude> direction (Right 5)
"you should go right 5 meters!"
Other uses (that we’ve seen so far!) of pattern matching can also be accomplished with the ==
operator. However, things like x==Nothing
won’t work in all cases. We’ll find out why when we talk about type classes in a later chapter.
Quiz
How many values does f x = [x,x]
return?
- Zero
- One
- Two
Why does the expression Nothing 1
cause a type error?
- Because
Nothing
takes no arguments - Because
Nothing
returns nothing - Because
Nothing
is a constructor
What is the type of the function f x y = if x && y then Right x else Left "foo"
?
Bool -> Bool -> Either Bool String
String -> String -> Either String String
Bool -> Bool -> Either String Bool
Which of the following functions could have the type Bool -> Int -> [Bool]
f x y = [0, y]
f x y = [x, True]
f x y = [y, True]
What is the type of this function? justBoth a b = [Just a, Just b]
a -> b -> [Maybe a, Maybe b]
a -> a -> [Just a]
a -> b -> [Maybe a]
a -> a -> [Maybe a]
Cheatsheet
Another cheatsheet, credits to our TA Daan Wichmann
import Data.List -- Importing module
-- Helper functions (e.g. when we want to accumulate something in recursion i.e. we need helper variables)
-- Function: calculating fibonnaci numbers efficiently
efficientFib :: Integer -> Integer
efficientFib n = efficientFib' 0 1 n -- Note the comma! This is a different function: a helper function
-- Our helper function
efficientFib' :: Integer -> Integer -> Integer -> Integer
efficientFib' a b 1 = b
efficientFib' a b n = efficientFib' b (a + b) (n - 1)
-- Guards
guessMyAge :: Int -> String
guessMyAge guess
| guess < 18 = "Too low!"
| guess > 22 = "Too high!"
| otherwise = "Close!"
-- Lists: lists are homogeneous is Haskell
tas :: [String] -- Lists are parameterized types, 'String' is a type parameter here.
tas = ["Daan", "Damai", "Ella", "Mateusz", "Paula"]
-- List operations
-- head :: [a] -> a -- returns the first element
-- last :: [a] -> a -- returns the last element
-- tail :: [a] -> [a] -- returns everything except the first element
-- init :: [a] -> [a] -- returns everything except the last element
-- take :: Int -> [a] -> [a] -- returns the n first elements
-- drop :: Int -> [a] -> [a] -- returns everything except the n first elements
-- (++) :: [a] -> [a] -> [a] -- lists are catenated with the ++ operator
-- (!!) :: [a] -> Int -> a -- lists are indexed with the !! operator (starts at 0)
-- reverse :: [a] -> [a] -- reverse a list
-- null :: [a] -> Bool -- is this list empty?
-- length :: [a] -> Int -- the length of a list
-- sort :: [a] -> [a] -- from the Data.List module
numberOfTAs :: Int
numberOfTAs = length tas
-- Ranges
digits :: [Int]
digits = [1..9] -- 1, 2, 3, 4, 5, 6, 7, 8, 9
evens :: [Int]
evens = [2,4..10] -- 2, 4, 6, 8, 10
countingDown :: [Int]
countingDown = [10,9..1] -- 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
infiniteRange :: [Int]
infiniteRange = [1,2..]
tenMultiplesOf2 :: [Int]
tenMultiplesOf2 = take 10 [2,4..] -- Possible because Haskell = lazy
cycleIntList :: [Int] -> Int -> [Int]
cycleIntList lst n = take n (cycle lst)
repeatInt :: Int -> Int -> [Int] -- Equivalent: replicate
repeatInt int n = take n (repeat int)
-- 'a' is a type variable
-- customHead is polymorphic
customHead :: [a] -> a
customHead lst = lst !! 0
-- Maybe
job :: String -> Maybe String
job "Bryan" = Just "Lecturer"
job "Emma" = Just "Lecturer"
job "Daan" = Just "TA"
job "Damai" = Just "TA"
job "Ella" = Just "TA"
job "Mateusz" = Just "TA"
job "Paula" = Just "TA"
job _ = Nothing
personel :: Maybe String -> [String]
personel (Just "TA") = ["Daan", "Damai", "Ella", "Mateusz", "Paula"]
personel (Just "Lecturer") = ["Bryan", "Emma"]
personel Nothing = ["Student A", "Student B"]
-- Either
readInt :: String -> Either String Int
readInt "0" = Right 0
readInt "1" = Right 1
readInt s = Left ("Unsupported string: " ++ s)
-- Case-of
parseCountry :: String -> Maybe String
parseCountry "FI" = Just "Finland"
parseCountry "SE" = Just "Sweden"
parseCountry _ = Nothing
flyTo :: String -> String
flyTo countryCode =
case parseCountry countryCode of
Just country -> "You're flying to " ++ country
Nothing -> "You're not flying anywhere"
-- Note: case-of expressions can always be rewritten to helper functions!
-- We can use case-of when we want to match against function outputs.
-- When we want to use local helper function in all cases.
-- Cleaner
You can check your current points from the blue blob in the bottom-right corner of the page.