1 / 26

Haskell

Haskell. Chapter 5, Part I. Topics. Higher Order Functions map, filter Infinite lists. Higher Order Functions. A function that can take functions as parameters OR A function that returns a function as result

lin
Download Presentation

Haskell

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Haskell Chapter 5, Part I

  2. Topics • Higher Order Functions • map, filter • Infinite lists

  3. Higher Order Functions • A function that can take functions as parameters • OR • A function that returns a function as result • Think of calculus. What sort of operation takes a function and returns another function?

  4. First simple example - map • Map (built in) takes a function and a list, applies function to every element in the list map' :: (a->b) -> [a] -> [b] map' _ [] = [] map' f (x:xs) = f x : map' f xs • Try: • map’ even [1,2,3,4,5] • map’ square [1,2,3,4,5] (assumes square is defined) • map’ (++ "!") ["snap", "crackle", "pop"] • map fst [(1,2), (3,5), (7,8)] • Can you explain the type signature?

  5. More mapping • map (+3) [4,7,9] • [x+3 | x <- [4,7,9]] -- equivalent, maybe less readable Nested maps • map (map (^2)) [[1,2],[3,4],[5,6]]

  6. Another simple example - filter • Takes a predicate function and a list, returns a list of elements that satisfy that predicate filter' :: (a -> Bool) -> [a] -> [a] filter' _ [] = [] filter' p (x:xs) | p x = x : filter' p xs | otherwise = filter' p xs • Try • filter' (>3) [1,2,4,6,3] • filter (== 3) [1,2,4,5]

  7. Sections • What if you want to partially apply an infix function, such as +, -, /, *? • Use parentheses: • (+3) • (subtract 4) needed; (-4) means negative 4, not subtraction • (/10) • (*5) • (/10) 200

  8. Quick exercise • Create a simple map that cubes the numbers in a list, • e.g., [1,2,3] => [1,8,27] • Create a map that takes a nested list and removes the first element of each list, • e.g., [[2,4,5],[5,6],[8,1,2]] => [[4,5],[6],[1,2]] • Using `elem` and filter, write a function initials that takes a string and returns initials, • e.g., “Cyndi Ann Rader” => “CAR” • Write a function named noEven that takes a nested list and returns a nested list of only the odd numbers. • e.g., noEven [[1,2,3],[4,6]] => [[1,3],[]]

  9. Infinite List Examples

  10. More interesting examples largestDivisible :: Integral a => a -> a largestDivisible num = head (filter p [100000,99999..]) where p x = x `mod` num == 0 • Goal: find the largest number under 100,000 that’s divisible by num • Note the infinite list… since we use only the head, this will stop as soon as there’s an element • Order of list is descending, so we get the largest • What is p??? It’s a predicate function created in the where. • Try it: • largestDivisible 3829 => 99554 • largestDivisible 113 => 99892 • largestDivisible 3 => 99999

  11. takeWhile • takeWhile takes a predicate and a list, returns elements as long as the predicate is true • sum (takeWhile (<10) [1..100]) • takeWhile (/= ' ') "what day is it?" • Find the sum of all odd squares < 10,000 • need to create squares • select only odd squares • stop when square >= 10,000 • sum (takeWhile (<10000) (filter odd (map (^2) [1..]))) • OR • sum (takeWhile (<10000) [m | m <- [n^2 | n <- [1..]], odd m])

  12. An Example

  13. A fun problem • Collatz sequence/chain • Start with any natural number • If the number is 1, stop • If the number is even, divide it by 2 • If the number is odd, multiply it by 3 and add 1 • Repeat with the result number • Example: start with 13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1 • Mathematicians theorize that for all starting numbers, the chain will finish at the number 1. • Our goal: for all starting numbers between 1 and 100, how many have Collatz chains with length > 15? Think about: what kinds of problems are we solving here?

  14. The code chain :: Integer -> [Integer] chain 1 = [1] chain n | even n = n : chain (n `div` 2) | odd n = n : chain (n*3 + 1) numLongChains :: Int numLongChains = length (filter isLong (map chain [1..100])) where isLongxs = length xs > 15

  15. Thunks* • Lists are lazy • [1,2,3,4] is really 1:2:3:4:[] • When first element is evaluated (e.g., by printing it), the rest of the list 2:3:4:[] is a promise of a list – known as a thunk • A thunk is a deferred computation * from chapter 9

  16. Curried Functions

  17. Curried Functions • Every function in Haskell officially takes one parameter • So, how have we been able to do functions that take two parameters? • They are curried functions. • Always take exactly one parameter • When called with that parameter, it returns a function that takes the next parameter • etc. until all parameters used

  18. A curried example • :t max => max :: Ord a => a -> a -> a • equivalent to max :: (Ord a) => a -> (a -> a) • max 4 5 === (max 4) 5 • (max 4) returns a partially applied function • Try: (max ((max 4) 5)) 3 max max 4 _ 4 max 5 _ max 4 5 max 5 3 5

  19. Can’t show a function *Main> (max 4) <interactive>:88:1: No instance for (Show (a0 -> a0)) arising from a use of `print' Possible fix: add an instance declaration for (Show (a0 -> a0)) In a stmt of an interactive GHCi command: print it • What?? • (max 4) produced a function of type (a0 -> a0) • But functions aren’t instances of Show, so GHCi doesn’t know how to display Compare to Scheme:

  20. Another example multThree :: Int -> Int -> Int -> Int multThree x y z = x * y * z • multThree 3 5 9 => 135 • ((multThree 3) 5) 9 * I’m not saying this is how it’s implemented… just a way to think about it… multThree multThree 3 3 multThree 3 5 multThree 15 multThree 15 9 135

  21. multThree continued multThree :: Int -> Int -> Int -> Int multThree x y z = x * y * z • multThree 3 5 9 => 135 • ((multThree 3) 5) 9 • multThree :: Int -> (Int -> (Int -> Int)) – equivalent • function takes Int, returns function of type (Int -> (Int ->Int)) • that function takes an Int, returns function of type (Int -> Int) • that function takes an Int, returns an Int multThree multThree 3 3 A multThree 3 5 multThree 15 B multThree 15 C 9 135

  22. Take advantage of currying You can store a partially applied function: *Main> let multTwoWithNine = multThree 9 *Main> multTwoWithNine 2 3 54 multTwoWithNine multThree multThree 9 _ _ 9 multTwoWithNine multTwoWithNine (9) 2 _ 2 multTwoWithNine 9 2 _ 54 3

  23. How could we use this? tenPctDiscount multThreeF multThreeF 10 _ _ .10 tenPctDiscount 4 tenPctDiscount 4 2 5 What if you wanted a 20% discount? 25%? Write the code in Play and Share

  24. Another Example doubleArea multThree multThree 2 2 doubleArea 4 doubleArea 4 40 5 Write the code in Play and Share

  25. Play and Share • Write a function doubleArea that takes a width and height and returns 2 * the area – making use of multThree (could clearly be done directly, but use multThree for curry practice). • doubleArea 4 5 => 40 • Write a function multThreeF that works with floating point values. (hint: use Num a as a class constraint) • Write a function tenPctDiscount that takes two numbers and calculates a 10% discount (using your multThreeF, of course) • tenPctDiscount 4 5 => 2.0 • Write a function named pctDiscount that takes a floating point and returns a partially applied function. Usage: • *Main> let sale = pctDiscount 0.5 • *Main> sale 4 5 • 10.0 • *Main> (pctDiscount 0.5) 4 5 • 10.0

  26. More Play and Share • Curried functions are convenient with map • Write a function total that takes a discount % and two numbers stored in a list, and returns the discount amount • total 0.1 [4,5] => 2.0 • Write a function totalTenPctthat returns a partially applied total function with discount set to 0.1 • Try using this with map: • map totalTenPct [[4,5],[8,10]] => [2.0, 8.0] • Play with other uses of map, e.g., • map (multThree 3 4) [5,6,7]

More Related