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..]