module L02B where
-- Examples from Week 2, lecture B
-- Higher-Order Functions
-- dave 2012-11-08
import Data.List(sort,group)
import Data.Char(isSpace)
import Test.QuickCheck
import Test.QuickCheck.Function -- for testing HO functions
------------------------------------------
verse =
"A dying mosquito exclaimed,\nA chemist has poisoned my brain!\nThe cause of his sorrow\nWas para-dichloro-\nDiphenyl-trichloroethane\n"
-- map examples, abs, shout
-- def with list comprehensions
map' f xs = [f x | x <- xs]
filter' p xs = [x | x <- xs, p x]
sum' [] = 0
sum' (n:ns) = n + sum' ns
and' [] = True
and' (b:bs) = b && and' bs
foldr' op b [] = b
foldr' op b (x:xs) = x `op` foldr' op b xs
-- foldr
-- foldr op z xs
-- foldl op z [a,b,c,d] == ((z `op` a) `op` b) ...
unlines' ss = foldr joinNl "" ss
where joinNl s1 s2 = s1 ++ "\n" ++ s2
-- takeLine, takeWord
takeLine "" = ""
takeLine (c:cs) | c /= '\n' = c:takeLine cs
| otherwise = ""
takeWord "" = ""
takeWord (c:cs) | not(isSpace c) = c:takeWord cs
| otherwise = ""
takeWhile' :: (a -> Bool) -> [a] -> [a]
takeWhile' p [] = []
takeWhile' p (x:xs)
| p x = x:takeWhile' p xs
| otherwise = []
-- takeLine'' cs = takeWhile' (\x -> x /= '\n') cs
takeLine'' = takeWhile' (/= '\n')
-- Another pattern: lines, commaSep
lines' [] = []
lines' css = takeWhile (/= '\n') css
: lines' (drop 1 (dropWhile (/= '\n') css))
nosh = "spam,eggs,chips,spam"
commSep [] = []
commSep css = takeWhile (/= ',') css
: commSep (drop 1 $ dropWhile (/= ',') css)
-- segments -- see slides
-------------------------------------
-- More ways to build functions: Partial application
-- redundant brackets in the type help explain partial application:
-- meaningless function
f :: Char -> (Bool -> (String -> String)) -- redundant brackets
f c b s = c:s ++ show (not b) ++ s
-- Eta reduction
-- f x = e x can be rewritten as f = e
-- f y x = e x --> f y = e
-- use hlint to find this kind of thing
-- Aside
-- Fixity. How do you know when to skip brackets?
-- $
-- Example Design (Slides)
-- Function composition
wordCount = unlines
. map (\(w,n) -> w ++ ": " ++ show n)
. map (\ws -> (head ws,length ws))
. group
. sort
. words
prop_mapmap (Fun _ f) (Fun _ g) xs = map f (map g xs) == map (f.g) xs
where types = (f :: Int -> Int, g :: Int -> Int)
-- foldr puzzles
-- foldr (:) ys xs
-- foldr atEndOf [] xs where y `atEndof` ys = ys ++ [y]
-- foldr (\y ys -> f y : ys) [] xs