Download Haskell 5A

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Mathematics of radio engineering wikipedia , lookup

Big O notation wikipedia , lookup

Functional decomposition wikipedia , lookup

Non-standard calculus wikipedia , lookup

Continuous function wikipedia , lookup

Principia Mathematica wikipedia , lookup

Dirac delta function wikipedia , lookup

Function (mathematics) wikipedia , lookup

History of the function concept wikipedia , lookup

Function of several real variables wikipedia , lookup

Transcript
Haskell
Chapter 5, Part I
Topics

Higher Order Functions


map, filter
Infinite lists
Get out a piece of paper… we’ll be doing lots of tracing
Higher Order Functions*
A function that can take a function 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?

Think of AI. What aspects of human behavior might you
model with a higher order function?
* note that there are 2 potential ways a function can be higher order.
Note that this does not just say a function makes use of 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]]
Trace this

On paper: write result
Think about how it works
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,6,3] Trace this, use code above
filter (== 3) [1,2,4,5]
Sections



What if you want to partially apply an infix function, such as +, -, /, *?
Can be right or left section (depends on which arg is missing)
Use parentheses:


(+3) or (3+)
(subtract 4) or (4-)









(-4) means negative 4, not subtraction
subtract is prefix, try: subtract 4 10
(/10) or (10/)
(*5) or (5*)
(/10) 200
map (/10) [1..3]
map (10/) [1..3]
map (subtract 4) [1..5]
map (4-) [1..5]
https://wiki.haskell.org/Section_of_an_infix_operator
First-class functions


In computer science, a programming language is said to
have first-class functions if it treats functions as firstclass citizens. (what???)
Specifically, this means the language supports



a) passing functions as arguments to other functions,
b) returning them as the values from other functions, and
c) assigning them to variables or storing them in data
structures.
https://en.wikipedia.org/wiki/First-class_function
First-class functions







public void myFn(x, fn);
myFn(5, 11); // yes, very common
myFn(5, doSomething()); // a) some languages yes, some no
return 5; // yes!
return doSomething(); // b) some languages yes, some no
x = 5; // yes!
x = doSomething(); // c) some languages yes, some no
https://en.wikipedia.org/wiki/First-class_function
First-class functions & FP



First-class functions are a necessity for the functional
programming style, in which the use of higher-order
functions is a standard practice.
In languages with first-class functions, the names of
functions do not have any special status; they are treated
like ordinary variables with a function type.
Some programming language theorists require support
for anonymous functions (function literals) as well.
Implementing First-Class Functions


There are certain implementation difficulties in passing
functions as arguments and returning them as results,
especially in the presence of non-local variables
introduced in nested and anonymous functions.
In early imperative languages these problems were
avoided by either not supporting functions as result types
(e.g. ALGOL 60, Pascal) or omitting nested functions and
thus non-local variables (e.g. C).
public void doIt() {
int x = 5;
public int calcIt() { return x*x; }
}
Key point: to understand language design, think about language implementation !
Implementing First-Class Functions


The early functional language Lisp took the approach of
dynamic scoping, where non-local variables refer to the
closest definition of that variable at the point where the
function is executed (we’ll do an exercise later).
Proper support for lexically scoped first-class functions
was introduced in Scheme and requires handling
references to functions as closures instead of bare
function pointers, which in turn makes garbage collection
a necessity.

lexically scoped = based on program text. We’ll also look at
this again later.
Quick exercise

Create a simple map that cubes the numbers in a list,


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 (assume only initials are caps),


e.g., [1,2,3] => [1,8,27]
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],[]]
Infinite List Examples
Example
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 (<30) (filter odd (map (^2) [1..])))
OR
sum (takeWhile (<30) [m | m <- [n^2 | n <- [1..]], odd m])
Trace this – pick either one
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
An Example
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 isLong xs = length xs > 15
13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
Discuss this
Curried Functions
What is currying?



currying is the technique of translating the evaluation of
a function that takes multiple arguments into evaluating a
sequence of functions, each with a single argument.
It was introduced by Moses Schönfinkel and later
developed by Haskell Curry (yes, Haskell is named after
Haskell Curry)
Why? There are analytical techniques that can only be
applied to functions with a single argument.
https://en.wikipedia.org/wiki/Currying
Curried example
For example, given the function: f(x,y) = y/x
 To evaluate f(2,3) , first replace with x with 2
 Since the result is a function of y, this new function g(y)
can be defined as g(y) = f(2,y) = y/2
 Next, replace the y argument with 3, producing
g(3) = f(2,3) = 3/2



On paper, this may be done in one step.
For program implementation, this can be done
sequentially. Each replacement results in a function taking
exactly one argument.
This produces a chain of functions (as in lambda calculus).
also from Wikipedia
Curried Functions in Haskell

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
Course theme: understand implementation to better understand language
JavaScript: objects are just hashes
Haskell: every function takes exactly one argument
Course theme: collections of features. Currying requires first-class functions.
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
max
4


Try: (max ((max 4) 5)) 3
Try: (max 4) 5
5
5
3
max 4
max 4 _
5
max 5 _
max
max 5
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
3
multThree
multThree
3
5
multThree
3
multThree
15
9
multThree
15
* I’m not saying this is how it’s
implemented… just a way to
think about it…
135
Note: we’ll do a floating point version in Play & Share
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
A.
B.
C.
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
A 3
multThree
multThree
3
B 5
multThree
3
multThree
15
C 9
multThree
15
135
Take advantage of currying
You can store a partially applied function:
*Main> let multTwoWithNine = multThree 9
*Main> multTwoWithNine 2 3
54
multTwoWithNine
multThree
9__
9
multThree
2
multTwoWithNine
multTwoWithNine
(9) 2 _
multTwoWithNine
92_
54
3
How could we use this?
tenPctDiscount
.10
4
5
multThreeF
tenPctDiscount
multThreeF
10 _ _
tenPctDiscount
4
2
What if you wanted a 20% discount? 25%?
Write the code in Play and Share
Another Example
doubleArea
2
4
multThree
doubleArea
multThree 2
doubleArea 4
40
5
Write the code in Play and Share
Why curry?
From http://engineering.cerner.com/blog/closures-and-currying-in-javascript



Currying can help you make higher order factories.
Currying can help you avoid continuously passing the
same variables.
Currying can memorize various things including state.
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).



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)


doubleArea 4 5 => 40
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

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
Curried functions are convenient with map
 Write a function totalTenPct that 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]