Lecture 6
Maps, Folds, and Beyond
F12, then click ConsoleF12, then click ConsoleCtrl+Shift+k↓, PgDn, n, j |
next slide |
↑, PgUp, p, k |
prev slide |
Esc |
enables ctrl+f globally |
-- Designed by Matthew A. Frazier
-- "I haven't actually tested it, but it compiles so it should work"
data Tree a = Leaf a | Node a (Tree a) (Tree a)
deriving (Show, Eq)
add :: Integral a => Tree a -> a
add (Leaf l) = l
add (Node i right left) = i + (add right) + (add left)
-- Designed by Rolph J. J. Recto
data Tree = Branch Int Tree Tree | Leaf Int | NullNode deriving (Show)
add :: Tree -> Int
add NullNode = 0
add (Leaf x) = x
add (Branch x left right) = x + (addTree left) + (addTree right)
-- Mastered by James C. Sun
-- download: https://gist.github.com/BinRoot/4983189
module BinaryTree
(Tree(..), makeTree, add, printTree)
where
data Tree = Tree Int Tree Tree | EMPTYTREE deriving (Show, Eq)
printTree :: Tree -> IO()
printTree tree = putStrLn (printSubTree tree 0 0)
nodeLinks = ["", "/", "\\"]
printSubTree :: Tree -> Int -> Int -> String
printSubTree EMPTYTREE _ _ = ""
printSubTree (Tree root leftSubTree rightSubTree) n link = (printSubTree leftSubTree (n+3) 1)
++ (replicate n ' ')
++ (nodeLinks !! link)
++ (show root) ++ "\n"
++ (printSubTree rightSubTree (n+3) 2)
makeTree :: Int -> Tree
makeTree n
| n < 0 = EMPTYTREE
| otherwise = Tree n (makeTree (n - 1)) (makeTree (n - 2))
add :: Tree -> Int
add EMPTYTREE = 0
add (Tree root leftSubTree rightSubTree) = root + (add leftSubTree) + (add rightSubTree)
-- Designed by Julien Letrouit
data Tree = Node {left::Tree, right::Tree, value::Int} | NilTree
treeSum NilTree = 0
treeSum node = value node + treeSum (left node) + treeSum (right node)
Functions can take functions as arguments
A map applies a function to each element of a list
Prelude> map even [1..10]
[False,True,False,True,False,True,False,True,False,True]
Prelude> map (+5) [1..10]
[6,7,8,9,10,11,12,13,14,15]
MapType signature:
map :: (a -> b) -> [a] -> [b]
Possible Implementation:
map f [] = []
map f (x:xs) = (f x):(map f xs)

piGuess :: Int -> Double
piGuess n = sum (map f [1..n])
f :: Int -> Double
f x = 4*(-1)^(x+1) / (2.0 * k - 1)
where k = fromIntegral x
Use a map! Bam!
A filter refines a list using a predicate
Prelude> filter even [1..10]
[2,4,6,8,10]
Prelude> filter (>5) [1..10]
[6,7,8,9,10]
FilterType signature:
filter :: (a -> Bool) -> [a] -> [a]
Possible Implementation:
filter p [] = []
filter p (x:xs) | p x = x : filter p xs
| otherwise = filter p xs
We can use λ-calculus to define a function
Prelude> map (\x -> x*x) [1..10]
[1,4,9,16,25,36,49,64,81,100]
This notation is inspired from lambda calculus
λx.(x*x)
Prelude> data Gender = Male | Female deriving (Show, Eq)
Prelude> let people = [(Male, "Mal"), (Female, "Zoe"),
(Male, "Wash"), (Female, "Inara"),
(Male, "Jayne"), (Female, "Kaylee")
(Male, "Simon"), (Female, "River")]
Prelude> filter (\(a,b) -> a==Female) people
[ (Female,"Zoe"), (Female,"Inara"),
(Female,"Kaylee"), (Female,"River") ]
Prelude> map snd it
["Zoe", "Inara", "Kaylee", "River"]
A fold scans an entire list to return a result
-- sum up all elements of a list
Prelude> foldl (+) 0 [1, 2, 3]
6
-- count the number of vowels in a String
Prelude> foldl (\acc x -> if x `elem` "aeiou"
then acc+1
else acc) 0 "hello world"
2
A scan shows the intermediate values of a fold
-- sum up all elements of a list
Prelude> scanl (+) 0 [1, 2, 3]
[0,1,3,6]
-- count the number of vowels in a String
Prelude> scanl (\acc x -> if x `elem` "aeiou"
then acc+1
else acc) 0 "hello world"
[0,0,1,1,1,2,2,2,3,3,3,3]
The ($) function is called a function application.
It makes functions right associative
Prelude> not odd 4
ERROR!
Prelude> not (odd 4)
True
Prelude> not $ odd 4
True
. FunctionIt composes functions in a readable manner
f(g(h(k(x)))) is ugly
(f.g.h.k)(x) is pretty
Prelude> (not.odd) 4
True
Prelude> (length.head.words) "University of Virginia"
10
These are only some of the functions in Prelude
Haskell comes with a bunch more:
...and more than 350 others!
Prelude> import Data.List
Prelude Data.List> concat ["under","stand","able"]
"understandable"
Prelude Data.List> any (==0) [1,1,1,1,1,0,1]
True
Prelude Data.List> sort "hello"
"ehllo"
...and over 200 more!
Prelude> import Data.Char
Prelude Data.Char> isNumber 'h'
False
Prelude Data.Char> toUpper 't'
'T'
Prelude Data.Char> map ord ['A'..'F']
[65,66,67,68,69,70]
...and over 100 more!
Prelude> import Data.Map
Prelude Data.Map> let m = fromList [("CS", "Computer Science"),
("PHIL", "Philosophy")
("ASTR", "Astronomy")]
Prelude Data.Map> keys m
["CS","PHIL","ASTR"]
Prelude Data.Map> Data.Map.lookup "CS" m
Just "Computer Science"
...and over 200 more!
Prelude> import Data.Set
Prelude Data.Set> let a = fromList [1..58]
Prelude Data.Set> let b = fromList [53..100]
Prelude Data.Set> intersection a b
fromList [53,54,55,56,57,58]
Prelude Data.Set> findMax $ union a b
100
...and around 100 more!
A strong password has
Prelude> :t strong
strong :: String -> Bool
Prelude> strong "sup3rL33Tpassw0rd"
True
Try to use tools you've learned this lecture