Download CITS3211 FUNCTIONAL PROGRAMMING 5. Higherorder functions

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

Closure (computer programming) wikipedia , lookup

Lambda calculus wikipedia , lookup

Lambda lifting wikipedia , lookup

C Sharp (programming language) wikipedia , lookup

Falcon (programming language) wikipedia , lookup

Anonymous function wikipedia , lookup

Combinatory logic wikipedia , lookup

Currying wikipedia , lookup

Standard ML wikipedia , lookup

Transcript
CITS3211
FUNCTIONAL PROGRAMMING
5. Higher­order functions
Summary: This lecture discusses higher­order programming in Haskell. Functions in Haskell are “first­class citizens”, meaning that you can do anything with functions that you can do with values of other types. This allows high­level programming techniques unavailable in imperative languages.
cs123 notes: Lectures 12–13
 R.L. While, 1997−2002, modified by R. Davies 2003­7.
Functions are first­class
•
Functions in Haskell are first­class citizens
•
Anything (non­type­specific) you can do with a number, a Boolean, a character, etc, you can also do with a function
•
−
functions can be passed as arguments
−
functions can be returned as results
−
functions can be stored in data structures
−
etc
e.g. flip, (.), ($), until
CITS3211 Functional Programming
2
5. Higher­order functions
Currying and partial application
•
Consider min1 and min2
min1 :: Ord a => a ­> a ­> a
min1 x y | x <= y = x
| x > y = y
min2 :: Ord a => (a, a) ­> a
min2 (x, y) | x <= y = x
| x > y = y
•
Clearly min1 x y == min2 (x, y), for all values of x and y
•
min1 is a curried function
− min1 takes one argument at a time
•
min2 is an uncurried function
− min2 takes both arguments together in a tuple
•
The built­in functions curry and uncurry convert between curried and uncurried functions.
CITS3211 Functional Programming
3
5. Higher­order functions
Partial application and sections
•
One simple way that a curried function f can return another function as its result is if f is partially applied, i.e. applied to fewer arguments than it expects
−
max 0 (:: Int ­> Int) returns positive arguments unchanged, but returns 0 for negative arguments
−
max 0 . min 100 (:: Int ­> Int) bounds its argument in the range 0…100
•
An infix operator can be partially applied to either its left argument or its right argument
−
this is known as a section
−
(+ 3) (:: Int ­> Int) adds 3 to its argument
−
(3 +) (:: Int ­> Int) adds 3 to its argument
−
(/ 2.0) (:: Float ­> Float) halves its argument
−
(2.0 /) (:: Float ­> Float) returns double the reciprocal of its argument
−
(++ “\n”) (:: String ­> String) adds a carriage return on the end of its argument
−
(“\n” ++) (:: String ­> String) adds a carriage return on the front of its argument (~= (‘\n’ :))
−
(: []) (:: a ­> [a]) makes its argument into a singleton list
−
([] :) (:: [[a]] ­> [[a]]) adds an empty list on the front of its argument
CITS3211 Functional Programming
4
5. Higher­order functions
Higher­order abstraction
•
•
Abstraction is the process of generalising a program by making its components into parameters of the program
− e.g. by naming an explicit constant
− this gives concise programs and reusable code
− it’s better to write one program and use it ten times than it is to write ten slightly­different programs
Consider asc’sort, which sorts a list into ascending order
asc’sort :: Ord a => [a] ­> [a] asc’sort []
= []
asc’sort (x : xs) = asc’sort [y | y <­ xs, y <= x] ++ [x] ++
asc’sort [y | y <­ xs, y > x]
•
Better is the generic sorting function gensort
gensort :: (a ­> a ­> Bool) ­> [a] ­> [a] gensort p []
= []
gensort p (x : xs) = gensort p [y | y <­ xs, p y x] ++ [x] ++
gensort p [y | y <­ xs, not (p y x)]
• Then we apply gensort to particular comparison functions
asc’sort :: Ord a => [a] ­> [a]
asc’sort = gensort (<=)
desc’sort :: Ord a => [a] ­> [a]
desc’sort = gensort (>=)
pair’sort :: Ord a => [(a, b)] ­> [(a, b)]
pair’sort = gensort cmpPair
where cmpPair (x, y) (u, v) = x <= u
CITS3211 Functional Programming
5
5. Higher­order functions
Higher­order abstraction—map
•
Consider the functions
add3, add4, add5 :: [Int] ­> [Int]
that add respectively 3, 4 and 5 to each element on a list
− it is better to define a single function addn :: Int ­> [Int] ­> [Int] that adds its first argument to each element in its second argument
•
Consider the functions
plus3, mul3, div3 :: [Int] ­> [Int]
that apply respectively (+ 3), (* 3) and (`div` 3) to each element on a list
− it is better to define a single function
applylist :: (Int ­> Int) ­> [Int] ­> [Int] that applies its first argument to each element in its second argument
•
map applies a function to each element in a list
map :: (a ­> b) ­> [a] ­> [b]
map f xs = [f x | x <­ xs]
CITS3211 Functional Programming
6
5. Higher­order functions
Higher­order abstraction—filter
•
Consider the functions
over’5, over’16, over’18 :: [Int] ­> [Int]
•
that select the ints over respectively 5, 16 and 18 from a list
− it is better to define a single function
over’n :: Int ­> [Int] ­> [Int]
that selects the integers over n from a list
Consider the functions
over’16, under’16, odds, evens :: [Int] ­> [Int]
that select the elements respectively over 16, under 16, odd and even from a list
−
it is better to define a single function filter’Ints :: (Int ­> Bool) ­> [Int] ­> [Int]
that uses its first argument to select elements from its •
second argument
filter uses a predicate to select elements from a list
filter :: (a ­> Bool) ­> [a] ­> [a]
filter p xs = [x | x <­ xs, p x]
•
Both map and filter treat the elements on a list independently
CITS3211 Functional Programming
7
5. Higher­order functions