Survey

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

Survey

Document related concepts

Transcript

CITS3211 FUNCTIONAL PROGRAMMING 5. Higherorder functions Summary: This lecture discusses higherorder programming in Haskell. Functions in Haskell are “firstclass citizens”, meaning that you can do anything with functions that you can do with values of other types. This allows highlevel programming techniques unavailable in imperative languages. cs123 notes: Lectures 12–13 R.L. While, 1997−2002, modified by R. Davies 20037. Functions are firstclass • Functions in Haskell are firstclass citizens • Anything (nontypespecific) 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. Higherorder 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 builtin functions curry and uncurry convert between curried and uncurried functions. CITS3211 Functional Programming 3 5. Higherorder 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. Higherorder functions Higherorder 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 slightlydifferent 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. Higherorder functions Higherorder 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. Higherorder functions Higherorder 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. Higherorder functions