Стандартное начало (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)) ([],[],[])