Haskell/Solutions/Lists II< Haskell | Solutions(Redirected from Haskell/Solutions/More about lists)
Note that, for our current purposes, it is indifferent whether to use
Integer, so don't worry if you have used one and the solutions below the other.
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
-- "Direct" solution with pattern matching. scanSum :: [Int] -> [Int] scanSum  =  scanSum [x] = [x] scanSum (x:y:xs) = x : scanSum ((x + y) : xs) -- Alternatively, using a helper function with an accumulator argument: scanSum :: [Int] -> [Int] scanSum = scanSum' 0 where -- The following type signature is entirely optional. -- We have added it just for extra clarity. scanSum' :: Int -> [Int] -> [Int] scanSum' tot  =  scanSum' tot (x:xs) = tot' : scanSum' tot' xs where tot' = x + tot -- Alternatively, using takeInt, dropInt and sumInt: scanSum :: [Int] -> [Int] scanSum  =  scanSum [x] = [x] scanSum (x:xs) = x : scanSum ((x + sumInt (takeInt 1 xs)) : dropInt 1 xs)
diffs :: [Int] -> [Int] diffs  =  diffs (x:xs) = diffs' (x:xs) xs where diffs' :: [Int] -> [Int] -> [Int] diffs' _  =  diffs'  _ =  diffs' (x:xs) (y:ys) = (y-x) : diffs' xs ys -- Alternatively, without the auxiliary function: diffs :: [Int] -> [Int] diffs  =  diffs [x] =  diffs (x:y:xs) = (y-x) : diffs (y:xs)
1. A handful of variations for each function will be shown below, in a single block:
negateList, negateList2 :: [Int] -> [Int] negateList = map negate negateList2 xs = map negate xs divisorsList, divisorsList2 :: [Int] -> [[Int]] divisorsList = map divisors divisorsList2 xs = map divisors xs -- Note that there are even more possible ways of writing this one. -- Remember that the dot operator composes functions: (g . f) x = g (f x) negateDivisorsList, negateDivisorsList2, negateDivisorsList3, negateDivisorsList4 :: [Int] -> [[Int]] negateDivisorsList = map (negateList . divisors) negateDivisorsList2 = map negateList . divisorsList negateDivisorsList3 list = map (negateList . divisors) list negateDivisorsList4 list = map (map negate) (map divisors list)
2. One possible solution:
import Data.List myRLEencoder :: String -> [(Int, Char)] myRLEencoder s = map pairRLE (group s) where pairRLE xs = (length xs, head xs) myRLEdecoder :: [(Int, Char)] -> String myRLEdecoder l = concat (map expandRLE l) where expandRLE (n, x) = replicate n x
N.B.: the RLE example is inspired from a blog post by Don Stewart on the same subject. If you are curious, check Don's post for a neat solution which likely won't not be immediately understandable, as it uses some things we didn't see yet.
Tips and tricksEdit
scanSum (takeInt 10 [1..]) and
takeInt 10 (scanSum [1..]) have the same value. This is possible because Haskell is a lazy language, thus in both cases the result is only evaluated as needed.
-- This is just like the Prelude function last. lastOf :: [a] -> a lastOf  = error "Empty list" lastOf [x] = x lastOf (_:xs) = lastOf xs -- This is just like the Prelude init. dropLast :: [a] -> [a] dropLast  = error "Empty list" dropLast [x] =  dropLast (x:xs) = x : (dropLast xs)