Haskell/Solutions/More about lists

From Wikibooks, the open-content textbooks collection

Jump to: navigation, search

← Back to More about lists


[edit] Lists

Exercises

Write the following functions and test them out. Don't forget the type declarations.

  1. takeInt returns the first n items in a list. So takeInt 4 [11,21,31,41,51,61] returns [11,21,31,41]
  2. dropInt drops the first n items in a list and returns the rest. so dropInt 3 [11,21,31,41,51] returns [41,51].
  3. sumInt returns the sum of the items in a list.
  4. scanSum adds the items in a list and returns a list of the running totals. So scanSum [2,3,4,5] returns [2,5,9,14]. Is there any difference between "scanSum (takeInt 10 [1..])" and "takeInt 10 (scanSum [1..])"?
  5. diffs returns a list of the differences between adjacent items. So diffs [3,5,6,8] returns [2,1,2]. (Hint: write a second function that takes two lists and finds the difference between corresponding items).

Again, in one block:

takeInt          :: Int -> [a] -> [a]
takeInt 0 _      = []
takeInt _ []     = []
takeInt n (x:xs) = x : takeInt (n-1) xs

dropInt          :: Int -> [a] -> [a]
dropInt 0 list   = list
dropInt _ []     = []
dropInt n (x:xs) = dropInt (n-1) xs

sumInt        :: [Int] -> Int
sumInt []     = 0
sumInt (x:xs) = x + sumInt xs

scanSum :: [Int] -> [Int]
scanSum = scanSum' 0
scanSum' :: Int -> [Int] -> [Int]
scanSum' tot [] = []
scanSum' tot (x:xs) = x + tot : scanSum' (x + tot) xs

diffs          :: [Int] -> [Int]
diffs []       = []
diffs (x:[])   = []
diffs (x:y:xs) = (y-x) : diffs (y:xs)

--alternative which uses the recommended second function:
diffsAlt :: [Int] -> [Int]
diffsAlt [] = []
diffsAlt (x:xs) = diffsAlt' (x:xs) xs
diffsAlt' :: [Int] -> [Int] -> [Int]
diffsAlt' _ [] = []
diffsAlt' [] _ = []
diffsAlt' (x:xs) (y:ys) = (y-x): diffsAlt' xs ys

Both scanSum (takeInt 10 [1..]) and takeInt 10 (scanSum [1..]) have the same value.

Exercises
Write a function which takes a list and a number and returns the given element.
--convention: takeElement list 0 returns the first element
takeElement :: [a] -> Integer -> a
takeElement []     _ = error "Index too large"
takeElement (x:_)  0 = x
takeElement (_:xs) n = takeElement xs (n-1)

This is a solution which uses head and tail which is what the section was about.

--convention: getIdx 1 list returns the first element
getIdx :: Integer -> [a] -> a
getIdx _ [] = error "Index too large"
getIdx 1 ls = head ls
getIdx n ls = getIdx (n-1) (tail ls)


Exercises
Write a function which will take a list and return only odd numbers greater than 1. Hint: isOdd can be defined as the negation of isEven.
oddGreaterThanOne list = [ n | n <- list, isOdd n, n > 1 ]
  where isOdd = not.isEven