Haskell/Solutions/列表 II
外观
请注意,对于我们目前的用途而言,使用Int
还是Integer
无关紧要,所以如果你使用了其中一个,而下面的解决方案使用了另一个,请不要担心。
1.
takeInt :: Int -> [a] -> [a]
takeInt 0 _ = []
takeInt _ [] = []
takeInt n (x:xs) = x : takeInt (n-1) xs
2.
dropInt :: Int -> [a] -> [a]
dropInt 0 list = list
dropInt _ [] = []
dropInt n (x:xs) = dropInt (n-1) xs
3.
sumInt :: [Int] -> Int
sumInt [] = 0
sumInt (x:xs) = x + sumInt xs
4.
-- "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)
5.
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. 每个函数的几种变体将在下面单独的代码块中显示
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. 一个可能的解决方案
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
注意:RLE 示例的灵感来自 Don Stewart 在同一主题上发表的一篇 博客文章。如果你好奇,可以查看 Don 的文章,其中有一个巧妙的解决方案,你可能无法立即理解,因为它使用了一些我们尚未见过的内容。
1. scanSum (takeInt 10 [1..])
和 takeInt 10 (scanSum [1..])
的值相同。这是可能的,因为 Haskell 是一种惰性语言,因此在这两种情况下,结果只有在需要时才会计算。
2.
-- 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)