lecture 9 polymorphism, overloading and higher order functions 1 polymorphism and overloading
TRANSCRIPT
Lecture 9 Polymorphism, Overloading and Higher Order Functions
1
Polymorphism and Overloading
Lecture 9 Polymorphism, Overloading and Higher Order Functions
2
[1,2,3,4,5,6] :: [Integer]
Prelude> ['a','b','c']++['d','e','f']
"abcdef" :: [Char]
Prelude> "abc"++"def"
"abcdef" :: [Char]
Prelude> ["abc","def","ghi"]++["uvw","xyz"]
["abc","def","ghi","uvw","xyz"] :: [[Char]]
What is the type of ++ :
[a] -> [a] -> [a]
Prelude> [1,2,3] ++ [4,5,6]
Lecture 9 Polymorphism, Overloading and Higher Order Functions
3
lengthList (x:xs) = 1 + lengthList xs
Main> lengthList ['a','b','c']
3 :: Integer
Main> lengthList [1,2,3,4,5,6]
6 :: Integer
Main> lengthList [['a','b','c'],['d','e','f'],['g'],['h','i']]
4 :: Integer
Main> lengthList ["abc","def"]
2 :: Integer
What is the type of lengthList?
[a] -> Int
lengthList [ ] = 0
Lecture 9 Polymorphism, Overloading and Higher Order Functions
4
In polymorphism type variables are used, as in:
[a] -> [a] -> [a]
[a] -> Int
(a,b) -> [a]
Polymorphism: “has many shapes”.
A function is polymorphic if it can operate on many different types. In
polymorphism, the same function definition is used for all the types it
is applied to.
The variable a stands for an arbitrary type. Of course all the a’s
in the first declaration above stand for the same type wheras in the
third, a and b can be different types.
Lecture 9 Polymorphism, Overloading and Higher Order Functions
5
Overloading is another mechanism for using the same function name on different types.
‘a’ = = ‘b’
(a,b) = = (c,d)
would require different definitions of “= =“.
(a = = c) && (b = = d)
An overloaded function has different definitions for different types.
Lecture 9 Polymorphism, Overloading and Higher Order Functions
6
Higher Order Functions
Lecture 9 Polymorphism, Overloading and Higher Order Functions
7
When we apply a function to all elements of a list, we say that we have mapped that function into the list. There is a Haskell built-in function called map that is used for this purpose.
map f list = [ f x | x <- list]
map f [ ] = [ ]
map f (first:rest) = f first : map f rest
Prelude> map odd [1,2,3,4,5][True,False,True,False,True]Prelude> map (^2) [1,2,3][1,4,9]Fact> map fact [3,4,5][6,24,120]
map: apply to all
A higher order function takes a function as an argument or returns a function as a result.
Lecture 9 Polymorphism, Overloading and Higher Order Functions
8
map :: ( a -> b) -> [a] -> [b]
Elements of the list to which the function is applied
Elements of the output list that the function returns
Type of map:
input function input list output list
Lecture 9 Polymorphism, Overloading and Higher Order Functions
9
A function which doubles all the values in a list of integers:
square :: Int -> Int square n = n^2 squareAll :: [Int] -> [Int] squareAll [ ] = [ ] squareAll (first : rest) = (square first) : (squareAll rest)
double :: Int -> Intdouble n = n*2 doubleAll :: [Int] -> [Int] doubleAll [ ] = [ ] doubleAll (first:rest) = (double first) : (doubleAll rest)
A function that squares all the values in a list of integers:
Lecture 9 Polymorphism, Overloading and Higher Order Functions
10
A function that returns a list of factorials of all the numbers in a given list of integers:
There is a pattern that is repeated in all these definitions. Here is where we can use a higher order function. We may write a general function:
doAll :: (Int -> Int) -> [Int] -> [Int] doAll f [ ] = [ ] doAll f (first : rest) = (f first ) : (doAll f rest)
All we need is this one general definition and the definitions of each of the functions to be applied to each element.
fact :: Int -> Intfact n = product [1..n] factAll :: [Int] -> [Int] factAll [ ] = [ ] factAll (first : rest) = (fact first) : (factAll rest)
Lecture 9 Polymorphism, Overloading and Higher Order Functions
11
double :: Int -> Int double n = n*2
square :: Int -> Int square n = n^2
fact :: Int -> Int fact n = product [1..n]
doAll :: (Int -> Int) -> [Int] -> [Int] doAll f [ ] = [ ] doAll f (first : rest) = (f first ) : (doAll f rest)
Main> doAll double [1,2,3,4]
[2,4,6,8]
Main> doAll fact [1,2,3,4]
[1,2,6,24]
Main> doAll square [1,2,3,4]
[1,4,9,16]
Lecture 9 Polymorphism, Overloading and Higher Order Functions
12
Alternatively, we could define all the functions in one line each using our higher order function doAll:
doubleAll2 :: [Int] -> [Int ] doubleAll2 list = doAll double list
squareAll2 :: [Int] -> [Int ] squareAll2 list = doAll square list
factAll2 :: [Int] -> [Int ] factAll2 list = doAll fact list
Main> factAll2 [1,2,3,4]
[1,2,6,24]
Main> doubleAll2 [1,2,3,4]
[2,4,6,8]
Main> doAll square [1,2,3,4]
[1,4,9,16]
Lecture 9 Polymorphism, Overloading and Higher Order Functions
13
We could even have used the built-in function map:
doubleAll = map double
where double x = 2*x
Main> doAll double [1,2,3,4]
[2,4,6,8]
Main> map double [1,2,3,4]
[2,4,6,8]
Main> doAll fact [1,2,3,4]
[1,2,6,24]
Main> map fact [1,2,3,4]
[1,2,6,24]
Main> doAll square [1,2,3,4]
[1,4,9,16] :: [Int]
Main> map square [1,2,3,4]
[1,4,9,16]
Main> doubleAll [1,2,3]
[2,4,6]
Lecture 9 Polymorphism, Overloading and Higher Order Functions
14
map:: (Int -> Int) -> ([Int] -> [Int]) -- “->”is right associative
So, we can define the following functions which return a function as their result:
doubleAll3 :: [Int] -> [Int ] doubleAll3 = map double
squareAll3 :: [Int] -> [Int] squareAll3 = map square
factAll3 :: [Int] -> [Int] factAll3 = map fact Main> squareAll3 [1,2,3,4,5]
[1,4,9,16,25] :: [Int]
We can think of map as a function which takes a function of type
Int -> Int and returns a function of type [Int] -> [Int] or:
Lecture 9 Polymorphism, Overloading and Higher Order Functions
15
Function remove (removes an element from a list):
remove _ [ ] = [ ]
remove element (first : rest) =
if element = = first then remove element rest
else first : (remove element rest)
We may want to write
a function that removes
all even or odd elements
or elements that satisfy
a certain condition.
removeOdd [ ] = [ ]
removeOdd (first:rest)
= if odd first
then removeOdd rest
else first : removeOdd rest
Main> removeOdd [1,2,3,4,5,6]
[2,4,6]
Filtering
Lecture 9 Polymorphism, Overloading and Higher Order Functions
16
removeEven [ ]=[ ]
removeEven (first : rest)= if even first
then removeEven rest
else first : removeEven rest
We can write a general function that does all of these.
removeAll p [ ] = [ ]
removeAll p (first : rest) = if p first
then removeAll p rest
else first : removeAll p rest
Main> removeEven [1,2,3,4,5,6]
[1,3,5]
Lecture 9 Polymorphism, Overloading and Higher Order Functions
17
Main> removeAll odd [1,2,3,4,5,6]
[2,4,6]
Main> removeAll even [1,2,3,4,5,6]
[1,3,5]
We could have used filter to do all this rather than defining removeAll. This is another useful built-in function. It takes a property and a list and returns a list containing the elements that have that property.
Main> filter odd [1,2,3,4,5,6]
[1,3,5]
Main> filter even [1,2,3,4,5,6,7]
[2,4,6]
Lecture 9 Polymorphism, Overloading and Higher Order Functions
18
filter :: ( a -> Bool) -> [a] -> [a]
The property is a function that returns a Bool
Elements of the input list, the output list that the function returns and the type that the property works on
Type of filter:
input function input list output list
Lecture 9 Polymorphism, Overloading and Higher Order Functions
19
Definition of filter
Fortunately, filter is a built-in function. If it wasn’t a built-in function, we could have defined filter as follows.
filter :: (Int -> Bool) -> [Int] -> [Int] filter p [ ] = [ ] filter p (first : rest) = if (p first) then first : (filter p rest) else filter p rest