Notes by Ernst Salzmann 2013.03.28 More FP _______________________________________________________________________________________________________________________ how would you do the length function? foldr:: (a-> b -> b) -> b [a] | | | | | -> empty list V V list result of the fold element on the tail const (+1) = \_ -> (+1) = \_ n -> n + 1 length:: [a] -> Int length = foldr(const (+1)) 0 length xs = foldr (+1) (map (const 1) xs) length xs = sum (map (const 1) xs) _______________________________________________________________________________________________________________________ This is how list is defined... data [a] = [] | a : [a] -- fake! data List a = Nil | Cons a (List a) | | V V ::list a Cons:: a -> List a -> List a > :t [] > [a] > :t (:) o + / \ / \ 1 o 1 + / \ / \ 2 o 2 + / \ / \ 3 o 3 + / \ / \ 4 Nil 4 > :t (:) > foldr (:) [] (1,2,3) > foldr (+) 0 [1,2,3] _______________________________________________________________________________________________________________________ > :t foldr > foldr :: (a -> b -> b) -> b -> [a] -> b data Tree a = Leaf | Branch (Tree a) a (Tree a) deriving Show foldTree :: (b -> a -> b -> b) -> b -> Tree a -> b foldTree branch leaf leaf = leaf foldTree branch leaf (Branch left x right) = branch (foldTree branch leaf left) x (foldTree branch leaf right) > foldTree (\l x r -> l + x + r) 0 (Branch Leaf 1 Leaf) > 1 > foldTree Branch Leaf (Branch Leaf 1 Leaf) > Branch Leaf 1 Leaf > foldTree Branch Leaf (Branch Leaf 1 (Branch 2 Leaf)) > Branch Leaf 1 (Branch Leaf 2 Leaf) > Branch Leaf 1 (Branch Leaf 2 Leaf) > foldTree (\l x r -> l + x + r) 0 (Branch Leaf 1 (Branch Leaf 2 Leaf)) > 3 _______________________________________________________________________________________________________________________ data Nat = Zero | Succ Nat deriving Show > Succ Zero foldNat :: b -> (b -> b) -> Nat -> b foldNat z s Zero = z fold z s (Succ n) = s (foldNat z s n) > foldNat 0 (+1) Zero > foldNat 0 (+1) Succ $ Succ Zero > :t ($!) > :t ($) > (+1) $! 1 > addNat (Succ Zero) (Succ Zero) > Succ (Succ Zero) _______________________________________________________________________________________________________________________ you can write "map" if you have "fold" map f = foldr (\x xs -> f x :xs) [] _______________________________________________________________________________________________________________________ MapReduce data = key/value pairs e.g. (url,txt) map (k,v) -> [k',v'] reduce k', [v'] -> v' Lets do an example: "I think therefore I think I am." think 2 I 3 therefore 1 am 1 map "I think ... " map (k,v) -> [k',v'] | V -> [ ("I",1) ("think",1) (therefore",1) ("I",1) ("think",1) ("I",1) ("am",1) ] reduce -> [ (I,1) (I,1) -> (I,3) (I,1)] [ (think,1) -> (think,2) (think,1)] map \(url,string) -> [(word,[url])] | V for every word in the document reduce = merge the lists _______________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________