-- | Higher-Order Functions 2 -- More examples of programming with higher-order functions -- Introduction Functional Programming 2019. {- This started as a skeleton, the definitions were filled in during the lecture. -} import Prelude hiding (product,and,or,foldr,concat,takeWhile,dropWhile, lines,words,zip,zipWith) import Data.Char import Test.QuickCheck -------------------------------------------------------------------------------- -- * More example of creating higher-order functions by generalising -- special cases: takeWhile, dropWhile, segments, lines, words weather = "June is warm\nJuly is warm\n\nJanuary is cold\n" {- Bad programming style -- | takeLine returns the first line of a text -- takeLine weather = "June is warm" takeLine :: String -> String takeLine (c:cs) | c/='\n' = c:takeLine cs takeLine _ = [] -- | takeWord returns the first word of a text takeWord :: String -> String takeWord (c:cs) | not (isSpace c) = c:takeWord cs takeWord _ = [] -} -- Identify the pattern, generalize takeWhile :: (a -> Bool) -> [a] -> [a] takeWhile p (c:cs) | p c = c:takeWhile p cs takeWhile p _ = [] takeLine s = takeWhile (/='\n') s takeWord s = takeWhile (not . isSpace) s -- A companion function dropWhile p (c:cs) | p c = dropWhile p cs dropWhile _ cs = cs --dropLine s = dropWhile (/='\n') s --dropWord s = dropWhile (not . isSpace) s dropLine = dropWhile (/='\n') dropWord = dropWhile (not . isSpace) prop_takeWhile_DropWhile p xs = takeWhile p xs ++ dropWhile p xs == xs -- | lines "abc\ndef\nghi" == ["abc","def","ghi"] --lines s = segments (/='\n') s lines = segments (/='\n') -- * Generalize lines segments p [] = [] segments p xs = takeWhile p xs : segments p (drop 1 (dropWhile p xs)) -- | words "abc def\nghi" = ["abc","def","ghi"] words :: String -> [String] --words s = filter (/="") (segments (not . isSpace) s) words = filter (/="") . segments (not . isSpace) -------------------------------------------------------------------------------- -- * zip, zipWith, uncurry -- https://en.wikipedia.org/wiki/Dot_product#Algebraic_definition -- Example: scalarProduct [4,5,6] [100,10,1] = 4*100 + 5*10 + 6*1 = 456 scalarProduct_v1 xs ys = sum [ x*y | (x,y) <- zip xs ys] scalarProduct_v2 xs ys = sum (map mul (zip xs ys)) where mul (x,y) = x*y scalarProduct_v3 xs ys = sum (map (uncurry (*)) (zip xs ys)) --zip :: [a] -> [b] -> [(a,b)] --zip (x:xs) (y:ys) = (x,y):zip xs ys --zip _ _ = [] zipWith :: (a->b->c) -> [a] -> [b] -> [c] zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys zipWith f _ _ = [] --zip xs ys = zipWith (,) xs ys zip = zipWith (,) scalarProduct xs ys = sum (zipWith (*) xs ys)