suffixes :: String -> [String] suffixes "Hello" ⇒ ["Hello", "ello", "llo", "lo

advertisement
C ONSTRUCTING L ISTS R ECURSIVELY
Compute all suffixes of a given string:
suffixes :: String -> [String]
For example,
suffixes "Hello"
⇒
["Hello", "ello", "llo", "lo", "o"]
➜ What is the base case?
(What happens in case of an empty string?)
➜ How does the recursive step proceed?
✧
C ONSTRUCTING L ISTS R ECURSIVELY
1
Overall, we have
suffixes
:: String -> [String]
suffixes "" = []
suffixes str = str : suffixes (tail str)
➜ We build the result list recursively using only [] and :.
➜ In fact, these two operators are enough to build any list.
➜ Usually, [] is called nil and : is called cons.
C ONSTRUCTING L ISTS R ECURSIVELY
2
Overall, we have
suffixes
:: String -> [String]
suffixes "" = []
suffixes str = str : suffixes (tail str)
➜ We build the result list recursively using only [] and :.
➜ In fact, these two operators are enough to build any list.
➜ Usually, [] is called nil and : is called cons.
C ONSTRUCTING L ISTS R ECURSIVELY
2- A
T HE
TRUTH ABOUT
L ISTS
Haskell thinks of lists as being built from nil ([]) and cons (:):
[x1 ,x2 ,x3 , . . . ,xn ] = x1 :(x2 :(x3 : · · · :(xn :[])))
✧
Notice::
➜ Repeated use of cons: recursive structure
➜ For each xi , there is one cons operator
➜ The list is terminated by nil
➜ The recursive representation is the original representation
➜ The closed notation (left hand side) is only a shorthand
T HE
TRUTH ABOUT
L ISTS
3
T HE
TRUTH ABOUT
L ISTS
Haskell thinks of lists as being built from nil ([]) and cons (:):
[x1 ,x2 ,x3 , . . . ,xn ] = x1 :(x2 :(x3 : · · · :(xn :[])))
✧
Notice::
➜ Repeated use of cons: recursive structure
➜ For each xi , there is one cons operator
➜ The list is terminated by nil
➜ The recursive representation is the original representation
➜ The closed notation (left hand side) is only a shorthand
T HE
TRUTH ABOUT
L ISTS
3- A
PATTERN M ATCHING
ON
L ISTS
We used pattern matching to decompose tuples:
fst
:: (a, b) -> a
fst (x, y) = x
fst ("Haskell", 7.1)
⇒
"Haskell"
➜ There is a symmetry between tuple construction and pattern
matching.
➜ The same holds for lists:
Using the elementary list constructors nil ([]) and cons (:), we
can decompose lists in the same way as we build them.
PATTERN M ATCHING
ON
L ISTS
4
PATTERN M ATCHING
ON
L ISTS
We used pattern matching to decompose tuples:
fst
:: (a, b) -> a
fst (x, y) = x
fst ("Haskell", 7.1)
⇒
"Haskell"
➜ There is a symmetry between tuple construction and pattern
matching.
➜ The same holds for lists:
Using the elementary list constructors nil ([]) and cons (:), we
can decompose lists in the same way as we build them.
PATTERN M ATCHING
ON
L ISTS
4- A
Extracting the head and tail via pattern matching:
head
:: [a] -> a
head (x:xs) = x
tail
:: [a] -> [a]
tail (x:xs) = xs
The functions head and tail yield the two arguments to cons.
✧
For every non-empty lists xs, we have
xs = head xs : tail xs
Therefore, in an expression x:xs, we often call
➜ x the head of the resulting list and
➜ xs the tail of the resulting list.
PATTERN M ATCHING
ON
L ISTS
5
Extracting the head and tail via pattern matching:
head
:: [a] -> a
head (x:xs) = x
tail
:: [a] -> [a]
tail (x:xs) = xs
The functions head and tail yield the two arguments to cons.
✧
For every non-empty lists xs, we have
xs = head xs : tail xs
Therefore, in an expression x:xs, we often call
➜ x the head of the resulting list and
➜ xs the tail of the resulting list.
PATTERN M ATCHING
ON
L ISTS
5- A
Both head and tail are partial functions:
➜ There is no case covering nil ([]).
For a total function, we have to provide two cases:
➜ one for nil ([]) and
➜ one for cons (:).
Check whether a given list is empty:
null
:: [a] -> Bool
null []
= True
null (x:xs) = False
✧
PATTERN M ATCHING
ON
L ISTS
6
Both head and tail are partial functions:
➜ There is no case covering nil ([]).
For a total function, we have to provide two cases:
➜ one for nil ([]) and
➜ one for cons (:).
Check whether a given list is empty:
null
:: [a] -> Bool
null []
= True
null (x:xs) = False
✧
PATTERN M ATCHING
ON
L ISTS
6- A
Both head and tail are partial functions:
➜ There is no case covering nil ([]).
For a total function, we have to provide two cases:
➜ one for nil ([]) and
➜ one for cons (:).
Check whether a given list is empty:
null
:: [a] -> Bool
null []
= True
null (x:xs) = False
✧
PATTERN M ATCHING
ON
L ISTS
6- B
L IST T RAVERSAL
So, let’s get back to the function
product [x1 , x2 , . . . , xn ] = x1 * x2 * · · · * xn
How can we define this function?
Considering the recursive nature of lists:
product (x1 : (x2 : . . . : (xn :
[])))
= x1 * x2 * · · · * xn
Bringing the right hand side in a corresponding form:
product (x1 : (x2 : . . . : (xn :
[])))
= (x1 * (x2 * · · · * (xn * 1)))
✧
L IST T RAVERSAL
7
L IST T RAVERSAL
So, let’s get back to the function
product [x1 , x2 , . . . , xn ] = x1 * x2 * · · · * xn
How can we define this function?
Considering the recursive nature of lists:
product (x1 : (x2 : . . . : (xn :
[])))
= x1 * x2 * · · · * xn
Bringing the right hand side in a corresponding form:
product (x1 : (x2 : . . . : (xn :
[])))
= (x1 * (x2 * · · · * (xn * 1)))
✧
L IST T RAVERSAL
7- A
L IST T RAVERSAL
So, let’s get back to the function
product [x1 , x2 , . . . , xn ] = x1 * x2 * · · · * xn
How can we define this function?
Considering the recursive nature of lists:
product (x1 : (x2 : . . . : (xn :
[])))
= x1 * x2 * · · · * xn
Bringing the right hand side in a corresponding form:
product (x1 : (x2 : . . . : (xn :
[])))
= (x1 * (x2 * · · · * (xn * 1)))
✧
L IST T RAVERSAL
7- B
The complete definition:
product
:: [Int] -> Int
product []
= 1
product (x:xs) = x * product xs
Some oberservations:
➜ The definition clearly replaces occurences of cons (:) by * and
the occurence of nil ([]) by 1.
➜ Functions mapping a list to an elementary value are called
reductions.
L IST T RAVERSAL
8
The complete definition:
product
:: [Int] -> Int
product []
= 1
product (x:xs) = x * product xs
Some oberservations:
➜ The definition clearly replaces occurences of cons (:) by * and
the occurence of nil ([]) by 1.
➜ Functions mapping a list to an elementary value are called
reductions.
L IST T RAVERSAL
8- A
M ORE L IST T RAVERSALS
product
:: [Int] -> Int
product []
= 1
product (x:xs) = x * product xs
How can we gain an understanding of how this works?
By executing the program stepwise.
Execution of product [3, 5, 6]:
product (3:(5:(6:[]))) ⇒
3 * product (5:(6:[]))
⇒
3 * 5 * product (6:[])
⇒
3 * 5 * 6 * product []
⇒
3 * 5 * 6 * 1
⇒
90
M ORE L IST T RAVERSALS
9
M ORE L IST T RAVERSALS
product
:: [Int] -> Int
product []
= 1
product (x:xs) = x * product xs
How can we gain an understanding of how this works?
By executing the program stepwise.
Execution of product [3, 5, 6]:
product (3:(5:(6:[]))) ⇒
3 * product (5:(6:[]))
⇒
3 * 5 * product (6:[])
⇒
3 * 5 * 6 * product []
⇒
3 * 5 * 6 * 1
⇒
90
M ORE L IST T RAVERSALS
9- A
M ORE L IST T RAVERSALS
product
:: [Int] -> Int
product []
= 1
product (x:xs) = x * product xs
How can we gain an understanding of how this works?
By executing the program stepwise.
Execution of product [3, 5, 6]:
product (3:(5:(6:[]))) ⇒
3 * product (5:(6:[]))
⇒
3 * 5 * product (6:[])
⇒
3 * 5 * 6 * product []
⇒
3 * 5 * 6 * 1
⇒
90
M ORE L IST T RAVERSALS
9- B
M ORE L IST T RAVERSALS
product
:: [Int] -> Int
product []
= 1
product (x:xs) = x * product xs
How can we gain an understanding of how this works?
By executing the program stepwise.
Execution of product [3, 5, 6]:
product (3:(5:(6:[]))) ⇒
3 * product (5:(6:[]))
⇒
3 * 5 * product (6:[])
⇒
3 * 5 * 6 * product []
⇒
3 * 5 * 6 * 1
⇒
90
M ORE L IST T RAVERSALS
9- C
M ORE L IST T RAVERSALS
product
:: [Int] -> Int
product []
= 1
product (x:xs) = x * product xs
How can we gain an understanding of how this works?
By executing the program stepwise.
Execution of product [3, 5, 6]:
product (3:(5:(6:[]))) ⇒
3 * product (5:(6:[]))
⇒
3 * 5 * product (6:[])
⇒
3 * 5 * 6 * product []
⇒
3 * 5 * 6 * 1
⇒
90
M ORE L IST T RAVERSALS
9- D
M ORE L IST T RAVERSALS
product
:: [Int] -> Int
product []
= 1
product (x:xs) = x * product xs
How can we gain an understanding of how this works?
By executing the program stepwise.
Execution of product [3, 5, 6]:
product (3:(5:(6:[]))) ⇒
3 * product (5:(6:[]))
⇒
3 * 5 * product (6:[])
⇒
3 * 5 * 6 * product []
⇒
3 * 5 * 6 * 1
⇒
90
M ORE L IST T RAVERSALS
9- E
M ORE L IST T RAVERSALS
product
:: [Int] -> Int
product []
= 1
product (x:xs) = x * product xs
How can we gain an understanding of how this works?
By executing the program stepwise.
Execution of product [3, 5, 6]:
product (3:(5:(6:[]))) ⇒
3 * product (5:(6:[]))
⇒
3 * 5 * product (6:[])
⇒
3 * 5 * 6 * product []
⇒
3 * 5 * 6 * 1
⇒
90
M ORE L IST T RAVERSALS
9- F
Concatenating Sublists:
➜ Lists can be nested, e.g.,
[[5, 6, 2], [], [4, 2]] :: [[Int]]
➜ concat merges sublists into one list, e.g.,
concat [[5, 6, 2], [], [4, 2]]
⇒
[5, 6, 2, 4, 2]
➜ What would a suitable specification of concat be?
concat [xs1 , xs2 , . . . , xsn ] = xs1 ++ xs2 ++ · · · ++ xsn
✧
Full definition:
concat
:: [[a]] -> [a]
concat []
= []
concat (xs:xss) = xs ++ concat xss
M ORE L IST T RAVERSALS
10
Concatenating Sublists:
➜ Lists can be nested, e.g.,
[[5, 6, 2], [], [4, 2]] :: [[Int]]
➜ concat merges sublists into one list, e.g.,
concat [[5, 6, 2], [], [4, 2]]
⇒
[5, 6, 2, 4, 2]
➜ What would a suitable specification of concat be?
concat [xs1 , xs2 , . . . , xsn ] = xs1 ++ xs2 ++ · · · ++ xsn
✧
Full definition:
concat
:: [[a]] -> [a]
concat []
= []
concat (xs:xss) = xs ++ concat xss
M ORE L IST T RAVERSALS
10- A
Concatenating Sublists:
➜ Lists can be nested, e.g.,
[[5, 6, 2], [], [4, 2]] :: [[Int]]
➜ concat merges sublists into one list, e.g.,
concat [[5, 6, 2], [], [4, 2]]
⇒
[5, 6, 2, 4, 2]
➜ What would a suitable specification of concat be?
concat [xs1 , xs2 , . . . , xsn ] = xs1 ++ xs2 ++ · · · ++ xsn
✧
Full definition:
concat
:: [[a]] -> [a]
concat []
= []
concat (xs:xss) = xs ++ concat xss
M ORE L IST T RAVERSALS
10- B
Concatenating Sublists:
➜ Lists can be nested, e.g.,
[[5, 6, 2], [], [4, 2]] :: [[Int]]
➜ concat merges sublists into one list, e.g.,
concat [[5, 6, 2], [], [4, 2]]
⇒
[5, 6, 2, 4, 2]
➜ What would a suitable specification of concat be?
concat [xs1 , xs2 , . . . , xsn ] = xs1 ++ xs2 ++ · · · ++ xsn
✧
Full definition:
concat
:: [[a]] -> [a]
concat []
= []
concat (xs:xss) = xs ++ concat xss
M ORE L IST T RAVERSALS
10- C
Concatenating Sublists:
➜ Lists can be nested, e.g.,
[[5, 6, 2], [], [4, 2]] :: [[Int]]
➜ concat merges sublists into one list, e.g.,
concat [[5, 6, 2], [], [4, 2]]
⇒
[5, 6, 2, 4, 2]
➜ What would a suitable specification of concat be?
concat [xs1 , xs2 , . . . , xsn ] = xs1 ++ xs2 ++ · · · ++ xsn
✧
Full definition:
concat
:: [[a]] -> [a]
concat []
= []
concat (xs:xss) = xs ++ concat xss
M ORE L IST T RAVERSALS
10- D
Download