- By
**lin** - Follow User

- 152 Views
- Uploaded on

Download Presentation
## Haskell

**An Image/Link below is provided (as is) to download presentation**

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript

### Haskell

Chapter 5, Part I

Topics

- Higher Order Functions
- map, filter
- Infinite lists

Higher Order Functions

- A function that can take functions as parameters
- OR
- A function that returns a function as result
- Think of calculus. What sort of operation takes a function and returns another function?

First simple example - map

- Map (built in) takes a function and a list, applies function to every element in the list

map' :: (a->b) -> [a] -> [b]

map' _ [] = []

map' f (x:xs) = f x : map' f xs

- Try:
- map’ even [1,2,3,4,5]
- map’ square [1,2,3,4,5] (assumes square is defined)
- map’ (++ "!") ["snap", "crackle", "pop"]
- map fst [(1,2), (3,5), (7,8)]
- Can you explain the type signature?

More mapping

- map (+3) [4,7,9]
- [x+3 | x <- [4,7,9]] -- equivalent, maybe less readable

Nested maps

- map (map (^2)) [[1,2],[3,4],[5,6]]

Another simple example - filter

- Takes a predicate function and a list, returns a list of elements that satisfy that predicate

filter' :: (a -> Bool) -> [a] -> [a]

filter' _ [] = []

filter' p (x:xs)

| p x = x : filter' p xs

| otherwise = filter' p xs

- Try
- filter' (>3) [1,2,4,6,3]
- filter (== 3) [1,2,4,5]

Sections

- What if you want to partially apply an infix function, such as +, -, /, *?
- Use parentheses:
- (+3)
- (subtract 4) needed; (-4) means negative 4, not subtraction
- (/10)
- (*5)
- (/10) 200

Quick exercise

- Create a simple map that cubes the numbers in a list,
- e.g., [1,2,3] => [1,8,27]
- Create a map that takes a nested list and removes the first element of each list,
- e.g., [[2,4,5],[5,6],[8,1,2]] => [[4,5],[6],[1,2]]
- Using `elem` and filter, write a function initials that takes a string and returns initials,
- e.g., “Cyndi Ann Rader” => “CAR”
- Write a function named noEven that takes a nested list and returns a nested list of only the odd numbers.
- e.g., noEven [[1,2,3],[4,6]] => [[1,3],[]]

More interesting examples

largestDivisible :: Integral a => a -> a

largestDivisible num = head (filter p [100000,99999..])

where p x = x `mod` num == 0

- Goal: find the largest number under 100,000 that’s divisible by num
- Note the infinite list… since we use only the head, this will stop as soon as there’s an element
- Order of list is descending, so we get the largest
- What is p??? It’s a predicate function created in the where.
- Try it:
- largestDivisible 3829 => 99554
- largestDivisible 113 => 99892
- largestDivisible 3 => 99999

takeWhile

- takeWhile takes a predicate and a list, returns elements as long as the predicate is true
- sum (takeWhile (<10) [1..100])
- takeWhile (/= ' ') "what day is it?"
- Find the sum of all odd squares < 10,000
- need to create squares
- select only odd squares
- stop when square >= 10,000
- sum (takeWhile (<10000) (filter odd (map (^2) [1..])))
- OR
- sum (takeWhile (<10000) [m | m <- [n^2 | n <- [1..]], odd m])

A fun problem

- Collatz sequence/chain
- Start with any natural number
- If the number is 1, stop
- If the number is even, divide it by 2
- If the number is odd, multiply it by 3 and add 1
- Repeat with the result number
- Example: start with 13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
- Mathematicians theorize that for all starting numbers, the chain will finish at the number 1.
- Our goal: for all starting numbers between 1 and 100, how many have Collatz chains with length > 15?

Think about: what kinds of problems are we solving here?

The code

chain :: Integer -> [Integer]

chain 1 = [1]

chain n

| even n = n : chain (n `div` 2)

| odd n = n : chain (n*3 + 1)

numLongChains :: Int

numLongChains = length (filter isLong (map chain [1..100]))

where isLongxs = length xs > 15

Thunks*

- Lists are lazy
- [1,2,3,4] is really 1:2:3:4:[]
- When first element is evaluated (e.g., by printing it), the rest of the list 2:3:4:[] is a promise of a list – known as a thunk
- A thunk is a deferred computation

* from chapter 9

Curried Functions

- Every function in Haskell officially takes one parameter
- So, how have we been able to do functions that take two parameters?
- They are curried functions.
- Always take exactly one parameter
- When called with that parameter, it returns a function that takes the next parameter
- etc. until all parameters used

A curried example

- :t max => max :: Ord a => a -> a -> a
- equivalent to max :: (Ord a) => a -> (a -> a)
- max 4 5 === (max 4) 5
- (max 4) returns a partially applied function
- Try: (max ((max 4) 5)) 3

max

max 4 _

4

max 5 _

max 4

5

max 5

3

5

Can’t show a function

*Main> (max 4)

<interactive>:88:1:

No instance for (Show (a0 -> a0))

arising from a use of `print'

Possible fix: add an instance declaration for (Show (a0 -> a0))

In a stmt of an interactive GHCi command: print it

- What??
- (max 4) produced a function of type (a0 -> a0)
- But functions aren’t instances of Show, so GHCi doesn’t know how to display

Compare to Scheme:

Another example

multThree :: Int -> Int -> Int -> Int

multThree x y z = x * y * z

- multThree 3 5 9 => 135
- ((multThree 3) 5) 9

* I’m not saying this is how it’s implemented… just a way to think about it…

multThree

multThree 3

3

multThree 3

5

multThree 15

multThree 15

9

135

multThree continued

multThree :: Int -> Int -> Int -> Int

multThree x y z = x * y * z

- multThree 3 5 9 => 135
- ((multThree 3) 5) 9
- multThree :: Int -> (Int -> (Int -> Int)) – equivalent
- function takes Int, returns function of type (Int -> (Int ->Int))
- that function takes an Int, returns function of type (Int -> Int)
- that function takes an Int, returns an Int

multThree

multThree 3

3

A

multThree 3

5

multThree 15

B

multThree 15

C

9

135

Take advantage of currying

You can store a partially applied function:

*Main> let multTwoWithNine = multThree 9

*Main> multTwoWithNine 2 3

54

multTwoWithNine

multThree

multThree 9 _ _

9

multTwoWithNine

multTwoWithNine

(9) 2 _

2

multTwoWithNine

9 2 _

54

3

How could we use this?

tenPctDiscount

multThreeF

multThreeF 10 _ _

.10

tenPctDiscount

4

tenPctDiscount

4

2

5

What if you wanted a 20% discount? 25%?

Write the code in Play and Share

Another Example

doubleArea

multThree

multThree 2

2

doubleArea

4

doubleArea 4

40

5

Write the code in Play and Share

Play and Share

- Write a function doubleArea that takes a width and height and returns 2 * the area – making use of multThree (could clearly be done directly, but use multThree for curry practice).
- doubleArea 4 5 => 40
- Write a function multThreeF that works with floating point values. (hint: use Num a as a class constraint)
- Write a function tenPctDiscount that takes two numbers and calculates a 10% discount (using your multThreeF, of course)
- tenPctDiscount 4 5 => 2.0
- Write a function named pctDiscount that takes a floating point and returns a partially applied function. Usage:
- *Main> let sale = pctDiscount 0.5
- *Main> sale 4 5
- 10.0
- *Main> (pctDiscount 0.5) 4 5
- 10.0

More Play and Share

- Curried functions are convenient with map
- Write a function total that takes a discount % and two numbers stored in a list, and returns the discount amount
- total 0.1 [4,5] => 2.0
- Write a function totalTenPctthat returns a partially applied total function with discount set to 0.1
- Try using this with map:
- map totalTenPct [[4,5],[8,10]] => [2.0, 8.0]
- Play with other uses of map, e.g.,
- map (multThree 3 4) [5,6,7]

Download Presentation

Connecting to Server..