Lecture 17-2
More Higher Order Functions - Continued
takewhile
This function takes while a condition is true.
> takeWhile (<=5) [1..10]
> [1,2,3,4,5]
This is different to filter
which only removes individual elements.
> takeWhile (\ x -> length x <= 2) ["ab","cd","efg"]
> ["ab", "cd"]
Implementation
takeWhile' :: (a -> Bool) -> [a] -> [a]
takeWhile' _ [] = []
takeWhile' f (x:xs)
| f x = x : takeWhile' f xs
| otherwise = []
dropWhile
This is the opposite of the previous function:
> dropWhile (==1) [1,1,2,2,3,3]
> [2,2,3,3]
You can also use functions:
> dropWhile (\ x -> x < 10 && x > 0) [1,2,3,10,4,5]
> [10,4,5]
Implementation
dropWhile' :: (A -> Bool) -> [a] -> [a]
dropWhile' _ [] = []
dropWhile' f (x:xs)
| f x = dropWhile' f xs
| otherwise = x:xs
takeWhile
& dropWhile
Example
This function splits up the words in a string into a list of strings containing no spaces.
split_words "" = []
split_words string =
let
first = takeWhile (/= ' ') string
up_to_space = dropWhile (\= ' ') string
after_space = dropWhile (== ' ') up_to_space
in
first : split_words after_space
> split_words "one two three"
> ["one","two","three"]
words
The function that was made in the last example has a standard implementation called words
.
unwords
This is the companion function to words
. They aren’t quite inverses as unwords
will put spaces inbetween each word.
zipWith
This function zips two lists together using a function:
> zipWith (+) [1,2,3] [4,5,6]
> [5,7,9]
> zipWith (\ x y -> if x then y else -y) [True, False, True] [1,2,3]
> [1,-2,-3]
Implementation
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
Examples
mult_by_pos list = zipWith (*) list [0..]
> mult_by_pos [1,2,3]
> [0,2,6]
interleave str1 str2 =
let
zipped = zipWith (\ x y -> [x,y]) str1 str2
in
concat zipped
> interleave "abc" "123"
> "a1b2c3"
In this example concat
is used to make lists of strings into a single string.
Exercises
-
getNumber string = takeWhile (\ x -> elem x ['0'..'9']) string
-
wordCount string = length $ words string
-
numberWords string = zip $ words string $ [1..]