130 likes | 523 Views
Haskell. Chapter 3, Part I. Pattern Matching. Pattern matching with tuples Pattern matching with list comprehensions As-patterns. Pattern Matching. In a function, you might use a pattern to determine what action to take
E N D
Haskell Chapter 3, Part I
Pattern Matching • Pattern matching with tuples • Pattern matching with list comprehensions • As-patterns
Pattern Matching • In a function, you might use a pattern to determine what action to take • In Haskell, you can create separate function bodies to relate to the patterns of interest. lucky :: Int -> String lucky 7 = "LUCKY NUMBER SEVEN!" lucky x = "Sorry, you're out of luck, pal!" • Patterns are checked from top to bottom • First it checks pattern 7. Then x. • name with lowercase letter (e.g., x) binds to anything
Pattern Matching, continued • It’s important to include a catch-all charName :: Char -> String charName 'a' = "Albert" charName 'b' = "Betty" charName 'c' = "Charles" • If put in any other character, see “Non-exhaustive patterns in function charName”
Pattern Matching and Recursion • Can use as base case for recursion (more on recursion in next chapter) factorial :: Int -> Int factorial 0 = 1 factorial n = n * factorial (n - 1)
Pattern Matching with Tuples addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double) addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
Pattern Matching to Extract Components first :: (a, b, c) -> a first (x, _, _) = x second :: (a, b, c) -> b second (_, y, _) = y third :: (a, b, c) -> c third (_, _, z) = z use _ to match values you don’t need to use later
Pattern Matching with Lists & List Comprehensions -- let xs = [(1,3), (4,3), (2,4)] addPairsxs = [a+b | (a, b) <- xs] • Remember list comprehensions from chapter 1 • The parameter xs is a list of tuples • Each element of the list in order matches with (a, b) • We then add a + b (remember items before | are the output) • Output elements are all concatenated into a list
Pattern Matching with Lists & List Comprehensions head' :: [a] -> a head' [] = error "Can't call head on an empty list, dummy!" head' (x:_) = x • To bind to several variables, must surround with parentheses (x:xs) • May look like a tuple, but the parentheses are just syntax to identify this as a pattern • error takes a string and generates an exception • can’t just return a string… because the return type must be the same as the elements in the list
More examples tell :: (Show a) => [a] -> String tell [] = "The list is empty" tell (x:[]) = "The list has one element " ++ show x tell (x:y:[]) = "The list has two elements: " ++ show x ++ " " ++ show y tell (x:y:_) = "The list is long. The first two elements are: " ++ show x ++ " " ++ show y • Note: you can’t use ++ in pattern matches • e.g., [1,2] ++ [3] -> [1,2,3]. BUT you can’t express that way in a pattern match.
As-patterns • Allows you to break up an item according to a pattern, but still keep a reference to the entire original item • To use, precede a regular pattern name with @ firstLetter :: String -> String firstLetter "" = "Empty string, whoops!" firstLetter all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]
Play and Share • Try to create type declarations for your methods • Use pattern matching to create a method named convertToOz, which can convert a number of gallons, quarts, pints, or cups to ounces. An error message is displayed if any other unit is entered. Example: • *Main> convertToOz "gallons" 3 • 384 • *Main> convertToOz "g" 3 • *** Exception: Unknown conversion factor • firstPair [3,4,5] [2,7] => (3,2) • multFirstTwo [3,4, 20, 30] => [12,20,30] (i.e., [3*4, 20, 30]) • area (3, 4) => "The area of rectangle with height 4 and width 3 is 12“ • Hint: use show Second area-related exercise: • width (3, 4) => 3 • height (3, 4) => 4 • tellArea (3, 4) => "Width: 3 Height: 4 Area: 12" • tellArea makes use of width and height. area does not. • Use an as-pattern for: insertList [1, 3, 4, 5] => [1,1,3,4,5,3,4,5] (i.e., take a list, create a new list consisting of first element, list, rest of elements)