Стандартное начало (Prelude)
8.1. Prelude PreludeList
- Стандартные функции над списками
module PreludeList (
map, (++), filter, concat, concatMap,
head, last, tail, init, null, length, (!!),
foldl, foldl1, scanl, scanl1, foldr, foldr1, scanr, scanr1,
iterate, repeat, replicate, cycle,
take, drop, splitAt, takeWhile, dropWhile, span, break,
lines, words, unlines, unwords, reverse, and, or,
any, all, elem, notElem, lookup,
sum, product, maximum, minimum,
zip, zip3, zipWith, zipWith3, unzip, unzip3)
where
import qualified Char(isSpace)
infixl 9 !!
infixr 5 ++
infix 4 `elem`, `notElem`- Отображение (map) и добавление в конец (append)
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : (xs ++ ys)
filter :: (a -> Bool) -> [a] -> [a]
filter p [] = []
filter p (x:xs) | p x = x : filter p xs
| otherwise = filter p xs
concat :: [[a]] -> [a]
concat xss = foldr (++) [] xss
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = concat . map f- head и tail извлекают соответственно первый и последний элементы - конечного списка. last и init являются - двойственными функциями, которые выполняются с конца конечного списка, - а не с начала.
head :: [a] -> a head (x:_) = x head [] = error "Prelude.head: пустой список" tail :: [a] -> [a] tail (_:xs) = xs tail [] = error "Prelude.tail: пустой список" last :: [a] -> a last [x] = x last (_:xs) = last xs last [] = error "Prelude.last: пустой список" init :: [a] -> [a] init [x] = [] init (x:xs) = x : init xs init [] = error "Prelude.init: пустой список" null :: [a] -> Bool null [] = True null (_:_) = False
- length возвращает длину конечного списка в виде Int.
length :: [a] -> Int length [] = 0 length (_:l) = 1 + length l
- Оператор доступа к элементам списка по индексу, начало - в 0.
(!!) :: [a] -> Int -> a xs !! n | n < 0 = error "Prelude.!!: отрицательный индекс" [] !! _ = error "Prelude.!!: слишком большой индекс" (x:_) !! 0 = x (_:xs) !! n = xs !! (n-1)
foldl, будучи примененной к своим аргументам: бинарному оператору, начальному значению (обычно - левому аргументу из тождества оператора) и списку, сокращает список, используя - бинарный оператор слева направо:
- foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn
foldl1 является вариантом предыдущей функции, она не имеет аргумента с начальным значением, и поэтому должна - применяться к непустым спискам. scanl похожа на foldl, но возвращает - список успешно сокращенных значений слева:
- scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
- Обратите внимание, что last (scanl f z xs) == foldl f z xs. - scanl1 похожа на предыдущую функцию, но без начального элемента:
- scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
foldl1 :: (a -> a -> a) -> [a] -> a
foldl1 f (x:xs) = foldl f x xs
foldl1 _ [] = error "Prelude.foldl1: пустой список"
scanl :: (a -> b -> a) -> a -> [b] -> [a]
scanl f q xs = q : (case xs of
[] -> []
x:xs -> scanl f (f q x) xs)
scanl1 :: (a -> a -> a) -> [a] -> [a]
scanl1 f (x:xs) = scanl f x xs
scanl1 _ [] = []- foldr, foldr1, scanr и scanr1 являются двойственными дополнениями описанных выше функций; - они действуют справа налево.
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
foldr1 :: (a -> a -> a) -> [a] -> a
foldr1 f [x] = x
foldr1 f (x:xs) = f x (foldr1 f xs)
foldr1 _ [] = error "Prelude.foldr1: пустой список"
scanr :: (a -> b -> b) -> b -> [a] -> [b]
scanr f q0 [] = [q0]
scanr f q0 (x:xs) = f x q : qs
where qs@(q:_) = scanr f q0 xs
scanr1 :: (a -> a -> a) -> [a] -> [a]
scanr1 f [] = []
scanr1 f [x] = [x]
scanr1 f (x:xs) = f x q : qs
where qs@(q:_) = scanr1 f xs- iterate f x возвращает бесконечный список повторных применений f к x:
- iterate f x == [x, f x, f (f x), ...] iterate :: (a -> a) -> a -> [a] iterate f x = x : iterate f (f x)
- repeat x представляет собой бесконечный список, где каждый элемент равен x.
repeat :: a -> [a] repeat x = xs where xs = x:xs
- replicate n x представляет собой список длины n, где каждый элемент равен x.
replicate :: Int -> a -> [a] replicate n x = take n (repeat x)
- cycle связывает конечный список в круговой или, что то же самое, - бесконечно повторяет исходный список. Он идентичен - бесконечным спискам.
cycle :: [a] -> [a] cycle [] = error "Prelude.cycle: пустой список" cycle xs = xs' where xs' = xs ++ xs'
- take n, будучи примененной к списку xs, возвращает префикс xs длины n, - или сам xs, если n > length xs. drop n xs возвращает суффикс xs - после первых n элементов, или [], если n > length xs. splitAt n xs - эквивалентна (take n xs, drop n xs).
take :: Int -> [a] -> [a] take n _ | n <= 0 = [] take _ [] = [] take n (x:xs) = x : take (n-1) xs drop :: Int -> [a] -> [a] drop n xs | n <= 0 = xs drop _ [] = [] drop n (_:xs) = drop (n-1) xs splitAt :: Int -> [a] -> ([a],[a]) splitAt n xs = (take n xs, drop n xs)
- akeWhile, будучи примененной к предикату p и списку xs, возвращает самый длинный - префикс (возможно пустой) xs, элементы которого удовлетворяют p. dropWhile p xs - возвращает оставшийся суффикс. span p xs эквивалентна - (takeWhile p xs, dropWhile p xs), тогда как break p использует отрицание p.
takeWhile :: (a -> Bool) -> [a] -> [a]
takeWhile p [] = []
takeWhile p (x:xs)
| p x = x : takeWhile p xs
| otherwise = []
dropWhile :: (a -> Bool) -> [a] -> [a]
dropWhile p [] = []
dropWhile p xs@(x:xs')
| p x = dropWhile p xs'
| otherwise = xs
span, break :: (a -> Bool) -> [a] -> ([a],[a])
span p [] = ([],[])
span p xs@(x:xs')
| p x = (x:ys,zs)
| otherwise = ([],xs)
where (ys,zs) = span p xs'
break p = span (not . p)- lines разбивает строку в местах символов новой строки на список строк. - Полученные строки не содержат символов новой строки. Аналогично, words - разбивает строку на список строк в местах пробельных символов. - unlines и unwords являются обратными операциями. - unlines соединяет строки, добавляя в конец каждой символ новой строки, а unwords соединяет - слова, отделяя их друг от друга пробелами.
lines :: String -> [String]
lines "" = []
lines s = let (l, s') = break (== '\n') s
in l : case s' of
[] -> []
(_:s'') -> lines s''
words :: String -> [String]
words s = case dropWhile Char.isSpace s of
"" -> []
s' -> w : words s''
where (w, s'') = break Char.isSpace s'
unlines :: [String] -> String
unlines = concatMap (++ "\n")
unwords :: [String] -> String
unwords [] = ""
unwords ws = foldr1 (\w s -> w ++ ' ':s) ws- reverse xs возвращает элементы списка xs в обратном порядке. Список xs должен быть конечным.
reverse :: [a] -> [a] reverse = foldl (flip (:)) []
- and возвращает конъюнкцию списка булевых значений. Для того чтобы результат - был истиной, список должен быть конечным; False является результатом наличия значения False - в элементе с конечным индексом конечного или бесконечного списка. or является двойственной к and функцией, - в ней используется дизъюнкция.
and, or :: [Bool] -> Bool and = foldr (&&) True or = foldr (||) False
- Будучи примененной к предикату и списку, any определяет, есть ли хотя бы один элемент - списка, который удовлетворяет предикату. Аналогично all определяет, все ли элементы списка удовлетворяет предикату.
any, all :: (a -> Bool) -> [a] -> Bool any p = or . map p all p = and . map p
- elem является предикатом, который определяет, является ли аргумент элементом списка; обычно он записывается в инфиксной форме, - например, x 'elem' xs. notElem является отрицанием предыдущей функции.
elem, notElem :: (Eq a) => a -> [a] -> Bool elem x = any (== x) notElem x = all (/= x)
- lookup key assoc ищет ключ в ассоциативном списке.
lookup :: (Eq a) => a -> [(a,b)] -> Maybe b
lookup key [] = Nothing
lookup key ((x,y):xys)
| key == x = Just y
| otherwise = lookup key xys- sum и product вычисляют соответственно сумму и произведение чисел из конечного списка.
sum, product :: (Num a) => [a] -> a sum = foldl (+) 0 product = foldl (*) 1
- maximum и minimum возвращают соответственно максимальное и минимальное значение из списка, - который должен быть непуст, конечен и содержать элементы, которые можно упорядочить.
maximum, minimum :: (Ord a) => [a] -> a maximum [] = error "Prelude.maximum: пустой список" maximum xs = foldl1 max xs minimum [] = error "Prelude.minimum: пустой список" minimum xs = foldl1 min xs
- zip принимает в качестве аргументов два списка и возвращает список соответствующих пар. Если один из - входных списков короче, дополнительные элементы более длинного списка игнорируются. - zip3 принимает в качестве аргументов три списка и возвращает список кортежей размера 3. Функции zip для более длинных кортежей - находятся в библиотеке List.
zip :: [a] -> [b] -> [(a,b)] zip = zipWith (,) zip3 :: [a] -> [b] -> [c] -> [(a,b,c)] zip3 = zipWith3 (,,)
- Семейство функций zipWith является обобщением семейства функций zip; они упаковывают элементы списков с помощью - функции, заданной в качестве первого аргумента, вместо функции создания кортежей. - Например, zipWith (+), будучи примененной к двум спискам, порождает список - соответствующих сумм.
zipWith :: (a->b->c) -> [a]->[b]->[c]
zipWith z (a:as) (b:bs)
= z a b : zipWith z as bs
zipWith _ _ _ = []
zipWith3 :: (a->b->c->d) -> [a]->[b]->[c]->[d]
zipWith3 z (a:as) (b:bs) (c:cs)
= z a b c : zipWith3 z as bs cs
zipWith3 _ _ _ _ = []- unzip преобразует список пар в пару списков.
unzip :: [(a,b)] -> ([a],[b])
unzip = foldr (\(a,b) ~(as,bs) -> (a:as,b:bs)) ([],[])
unzip3 :: [(a,b,c)] -> ([a],[b],[c])
unzip3 = foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))
([],[],[])