Haskell - PowerPoint PPT Presentation

1 / 35
About This Presentation
Title:

Haskell

Description:

Higher-Order functions. applyTwice :: (a - a) - a - a. applyTwice f x = f (f x) (a - a) is a function. parentheses are needed. a is (of course) a type parameter ... – PowerPoint PPT presentation

Number of Views:288
Avg rating:3.0/5.0
Slides: 36
Provided by: minesEdu
Category:
Tags: haskell

less

Transcript and Presenter's Notes

Title: Haskell


1
Haskell
  • Chapter 5, Part II

2
Topics
  • Review/More Higher Order Functions
  • Lambda functions
  • Folds

3
Higher Order Functions
4
Higher-Order functions
  • applyTwice (a -gt a) -gt a -gt a
  • applyTwice f x f (f x)
  • (a -gt a) is a function
  • parentheses are needed.
  • a is (of course) a type parameter, maybe Int,
    String, etc.
  • BUT, parameter and result must have the same type
  • Try
  • applyTwice(3) 10
  • applyTwice ( " woot") "say"
  • applyTwice (3) 1
  • Note that we are passing partially applied
    functions (e.g., 3, 3, etc.)

5
Example zipWith
  • zipWith' (a -gt b -gt c) -gt a -gt b -gt c
  • zipWith' _ _
  • zipWith' _ _
  • zipWith' f (xxs) (yys) f x y zipWith' f xs
    ys
  • joins two lists by applying function to
    corresponding elements
  • must handle cases where lists are not equal
    length
  • lists dont need to have same type
  • Try
  • zipWith' () 4,2,5 2,6,2
  • zipWith' (max) 4,2,5, 3 2,6,2
  • zipWith' () "foo ", "bar " "fighters",
    "bells"
  • zipWith' () (replicate 5 2) 1.. // replicates
    2 5x
  • zipWith' (zipWith' ()) 2,3,4,6
    10,20,100, 200

6
Example flip
  • flip' (a-gtb-gtc) -gt (b -gt a -gt c)
  • flip' f g
  • where g x y f y x
  • Try
  • zip 1,2,3,4,5 "hello"
  • flip' zip 1,2,3,4,5 "hello"
  • zip "hello" 1,2,3,4,5
  • let subIt x y x - y
  • let subItFlipped flip subIt
  • subIt 5 3
  • subItFlipped 5 3

Why would this be useful?
7
Flip Example
  • 1..10 !! 3 gt 4
  • infix operator, list first, followed by ix
  • What if we want to define a function that
    curries the index? First look at type
    signatures. We want a function that takes the
    index first, so we can curry it.
  • Maingt t (!!)
  • (!!) a -gt Int -gt a
  • This is not quite what we want curries first arg
    which is the list, not the ix
  • Maingt let curryIx (1..10 !!)
  • Maingt curryIx 4
  • Maingt t (flip (!!))
  • (flip (!!)) Int -gt c -gt c
  • let nth ix (flip (!!)) ix
  • let fourth nth 4
  • fourth 1..10
  • fourth 20,19..1

http//www.cs.arizona.edu/collberg/Teaching/372/2
008/Html/Html-10/index.html
8
Lambda
9
Lambda - l
  • Anonymous function we use when that function is
    only needed once
  • Typically use to pass to a higher-order function
  • Syntax
  • \ (kind of like l)
  • function parameters
  • -gt
  • function body
  • Example
  • numLongChains Int
  • numLongChains length (filter (\xs -gt length xs
    gt 15) (map chain 1..100))
  • compare to
  • numLongChains Int
  • numLongChains length (filter isLong (map chain
    1..100))
  • where isLong xs length xs gt 15

10
When not to use lambda
  • Dont use lambda when currying and partial
    application work those are more readable
  • Example, use
  • map (3) 1,6,3,2
  • Not
  • map (\x -gt x 3) 1,6,3,2
  • Both work... but which would you rather read??

11
More on lambda functions
  • They can take multiple parameters
  • zipWith (\a b -gt (a 30 3) / b) 5,4,3,2,1
    1,2,3,4,5
  • Can include pattern matching
  • BUT, only one pattern (cant fall through as in
    normal functions)
  • map (\(a, b) -gt a b) (1,2),(3,4)

12
Folds
13
Folds
  • A programming language can make it quicker to
    write code if it includes language constructs
    that capture common patterns
  • Think about common recursive pattern
  • Base case empty list
  • Pattern match xxs
  • Perform some action on x and (recursively) on xs
  • In Haskell, this is what a fold does!
  • Can be used whenever you want to traverse a list
    once and return something.

14
Example recursive sum
  • mySum (Num a) gt a -gt a -gt a
  • mySum acc acc
  • mySum acc (xxs) mySum (xacc) xs
  • Maingt mySum 0 2,4,5
  • 11

Trace with your partner
15
More details
  • A fold takes
  • A binary function (e.g., , div, etc.)
  • A starting value (accumulator)
  • A list to fold up
  • foldl () 0 2,4,5
  • sum' (Num a) gt a -gt a
  • sum' xs foldl (\acc x -gt acc x) 0 xs
  • sum' 2,4,5
  • 0 2
  • 2 4
  • 6 5
  • 11

2,4,5
acc 0
fold
4,5
acc 2
fold
5
acc 6
fold

acc 11
fold
16
Can use currying
  • sum'' (Num a) gt a -gt a
  • sum'' foldl () 0
  • Maingt sum'' 3,5
  • 8
  • What happened to xs? The above returns a
    partially applied function that takes a list.
  • In general, if have foo a bar b a
  • can rewrite as foo bar b
  • then call foo a
  • Note that the definition is more concise without
    the lambda

17
Quick Exercise
  • sum could be done as a fold at the command line,
    e.g.,
  • Maingt foldl () 0 3,4,5
  • 12
  • EXERCISE
  • Use a fold1 to create the product of the numbers
    in a list (just do this at the GHCi prompt, no
    function definition)
  • Use a foldl to append strings stored in a list to
    an initial string of Hello
  • Use a foldl to subtract a list of numbers from an
    initial value (could be subtracting purchases
    from your wallet, for example)

18
Right folds
19
Right folds
  • foldr is like foldl, except it eats up the
    values starting from the right.
  • In some cases, the result is the same.
  • Maingt foldl () 0 3,4,5
  • 12
  • Maingt foldr () 0 3,4,5
  • 12

2,4,5
acc 0
fold
2, 4
acc 5
fold
2
acc 9
fold

acc 11
fold
20
Right folds
  • The accumulator value of a fold can be any type
    including a list.
  • Maingt foldr (\x acc -gt (2) xacc) 2,3,4
  • 4,9,16
  • Note that the order of the arguments is reversed
    from the order of the parameters to lambda
    function
  • x acc parameters
  • 2,3,4 arguments
  • compare to left
  • foldl (\acc x -gt acc x) 0 2,3,4

2,3, 4
acc
fold
2, 3
acc 16
fold
2
acc 9, 16
fold

acc 4,9,16
fold
21
Right folds
  • If arguments not reversed
  • Maingt foldr (\x acc -gt (2) xacc) 2,3,4
  • 2,3,4
  • (nothing to eat up so resultacc)


acc 2,3,4
fold
22
Can I trace this?
  • scanl and scanr (and scanl1, scanr1) are like
    foldl and foldr, except they report intermediate
    accumulator states.
  • Used to monitor the progress of a function that
    can be implemented as a fold. Note the reverse
    order in which acc values show up in the list.
  • Maingt foldl () 0 3,5,2,1
  • 11
  • Maingt scanl () 0 3,5,2,1
  • 0,3,8,10,11
  • Maingt foldr (\x acc -gt (2) xacc) 2,3,4
  • 4,9,16
  • Maingt scanr (\x acc -gt (2) xacc) 2,3,4
  • 4,9,16 ,9,16,16,
  • Maingt scanr (\x acc -gt (2) xacc) 2,3,4
  • 2,3,4

23
Right folds to implement map
  • Like what we just did
  • foldr (\x acc -gt (2) xacc) 2,3,4
  • BUT use function passed as argument rather than
    2
  • map' (a -gt b) -gt a -gt b
  • map' f xs foldr (\x acc -gt f x acc) xs
  • map' (3) 1,2,3
  • 6 (x3, xs1,2)
  • 5 6 (x2, xs1)
  • 4 5, 6 (x1, xs)
  • 4,5,6

24
Which to use?
  • Could have done map with left fold
  • map'' (a -gt b) -gt a -gt b
  • map'' f xs foldl (\acc x -gt acc f x) xs
  • Note that is slower than
  • (why would that make sense?)
  • SO, map' will be faster than map''

25
Another example with Bool acc
  • elem' (Eq a) gt a -gt a -gt Bool
  • elem' y ys foldr (\x acc -gt if x y then True
    else acc) False ys
  • Note that accumulator starts with False
  • This code will work with an empty list

elem' 'c' 'a'..'d' Trace with your
partner (well do another one in a minute)
26
Two more folds
  • foldr1 and foldl1
  • Like foldr and foldl, but first (or last) element
    of the list is the starting value
  • Cant be called with empty list
  • Maingt scanl1 () 2,3,4
  • 2,5,9
  • Maingt scanl () 0 2,3,4
  • 0,2,5,9
  • foldl max 0 4,6,2
  • foldl1 max -4,-6,-2

27
foldl vs foldr
  • Try these
  • foldr (subtract) 0 5,4,3
  • scanr (subtract) 0 5,4,3
  • scanr (-) 0 5,4,3
  • foldl (subtract) 0 5,4,3
  • scanl (subtract) 0 5,4,3
  • foldl (flip (subtract)) 0 5,4,3
  • foldl1 (subtract) 5,4,3
  • scanl1 (flip (subtract)) 5,4,3

http//stackoverflow.com/questions/4454559/curryin
g-subtraction https//wiki.haskell.org/Unary_opera
tor https//www.haskell.org/hoogle/?hooglesubtrac
t
28
More fold examples
  • reverse' a -gt a
  • reverse' foldl (\acc x -gt x acc)
  • OR
  • reverse'' a -gt a
  • reverse'' foldl (flip ())
  • Quick exercise
  • Trace reverse'' 1,2,3
  • Remember flip f x y f y x
  • Hint use scanl if youre stuck on this

29
More fold examples
  • filter' (a -gt Bool) -gt a -gt a
  • filter' p foldr (\x acc -gt if p x then x acc
    else acc)
  • last' a -gt a
  • last' foldl1 (\_ x -gt x)

30
Play and Share higher order functions
  • Write a function divisibleBy such that
    divisibleBy 2 4 returns True, divisibleBy 2 5
    returns False
  • Try map (divisibleBy 2) 2,3,4
  • Write a function divisibleByFive that returns a
    partially applied divisibleBy function
  • Try map divisibleByFive 2,4,5
  • Write isDivisibleByFive that uses a lambda
    function with map to achieve the same result
    (e.g., returns False, False, True for 2,4,5)
  • Suggested by a former student
  • Create a higher-order function named integrate
    that takes a function, range, and step size and
    computes approximate numerical integration by
    evaluating the function at each step.
  • Maingt integrate square 2 4 0.001
  • 18.66066700000209
  • Maingt integrate cube 2 4 0.001
  • 59.97200299999252

31
Sidebar
32
Another look at folds
  • Can view as successive applications of some
    function to elements in a list
  • Assume right fold, binary function f, starting
    acc z
  • do foldr on 3,4,5,6
  • this is essentially
  • f (f (f ( f z 6) 5) 4) 3
  • If f is and starting value is 0, this is
  • (((6 0) 5) 4) 3 gt 18
  • If f is subtract and starting value is 0, this
    is
  • (((0 6) 5) 4) 3 gt -18
  • compare to foldl 6 - (5 - (4 - (3 0))) gt 2

33
Using and with infinite list
  • repeat False
  • False (False (False (False .
  • Haskell is lazy. Only generates items as needed.
  • returns False if one of its parameters is
    False.
  • () Bool -gt Bool -gt Bool
  • True x x
  • False _ False
  • Maingt and' (repeat False)
  • False
  • Foldr works with infinite lists IF binary
    function doesnt always evaluate its second
    parameter (as in ). Will not work with
    infinite lists if second parameter is always
    needed.

34
Another look at infinite lists
  • For foldl the recursion is
  • f (... (f ( f (f z x1) x2) x3) ...) xn
  • For foldr the recursion is
  • f x1 (f x2 (f x3 (...(f xn z) ...)))
  • So foldl must get to the end of the list. foldr,
    however, evaluates the function with the first
    element, then lazily evaluates the rest. So a
    function that can determine the final result
    based on the left-hand operand can be used with
    foldr and an infinite list.

http//lambda.jstolarek.com/2012/09/why-foldr-work
s-for-infinite-lists-and-foldl-doesnt/
35
Folds and infinite lists
  • returns True if all elements are True, False
    if any element is False
  • So as soon as a False is encountered, the result
    is False
  • and' Bool -gt Bool
  • and' xs foldr () True xs
  • and True, False, True
  • True (False (True True))
  • Try scanr () True True, False
Write a Comment
User Comments (0)
About PowerShow.com