4e987026 |
-- Standard list functions
-- build really shouldn't be exported, but what the heck.
-- some of the helper functions in this file shouldn't be
-- exported either!
module PreludeList (PreludeList.., foldr, build) where
import PreludePrims(build, foldr)
{-#Prelude#-} -- Indicates definitions of compiler prelude symbols
infixl 9 !!
infix 5 \\
infixr 5 ++
infix 4 `elem`, `notElem`
-- These are primitives used by the deforestation stuff in the optimizer.
-- the optimizer will turn references to foldr and build into
-- inlineFoldr and inlineBuild, respectively, but doesn't want to
-- necessarily inline all references immediately.
inlineFoldr :: (a -> b -> b) -> b -> [a] -> b
inlineFoldr f z l =
let foldr' [] = z
foldr' (x:xs) = f x (foldr' xs)
in foldr' l
{-# inlineFoldr :: Inline #-}
inlineBuild :: ((a -> [a] -> [a]) -> [b] -> [c]) -> [c]
inlineBuild g = g (:) []
{-# inlineBuild :: Inline #-}
-- head and tail extract the first element and remaining elements,
-- respectively, of a list, which must be non-empty. last and init
-- are the dual functions working from the end of a finite list,
-- rather than the beginning.
head :: [a] -> a
head (x:_) = x
head [] = error "head{PreludeList}: head []"
last :: [a] -> a
last [x] = x
last (_:xs) = last xs
last [] = error "last{PreludeList}: last []"
tail :: [a] -> [a]
tail (_:xs) = xs
tail [] = error "tail{PreludeList}: tail []"
init :: [a] -> [a]
init [x] = []
init (x:xs) = x : init xs
init [] = error "init{PreludeList}: init []"
-- null determines if a list is empty.
null :: [a] -> Bool
null [] = True
null (_:_) = False
-- list concatenation (right-associative)
(++) :: [a] -> [a] -> [a]
xs ++ ys = build (\ c n -> foldr c (foldr c n ys) xs)
{-# (++) :: Inline #-}
-- the first occurrence of each element of ys in turn (if any)
-- has been removed from xs. Thus, (xs ++ ys) \\ xs == ys.
(\\) :: (Eq a) => [a] -> [a] -> [a]
(\\) = foldl del
where [] `del` _ = []
(x:xs) `del` y
| x == y = xs
| otherwise = x : xs `del` y
-- length returns the length of a finite list as an Int; it is an instance
-- of the more general genericLength, the result type of which may be
-- any kind of number.
genericLength :: (Num a) => [b] -> a
genericLength l = foldr (\ x n -> 1 + n) 0 l
--genericLength [] = 0
--genericLength (x:xs) = 1 + genericLength xs
{-# genericLength :: Inline #-}
length :: [a] -> Int
length l = foldr (\ x n -> 1 + n) 0 l
--length [] = 0
--length (x:xs) = 1 + length xs
{-# length :: Inline #-}
-- List index (subscript) operator, 0-origin
(!!) :: (Integral a) => [b] -> a -> b
l !! i = nth l (fromIntegral i)
{-# (!!) :: Inline #-}
nth :: [b] -> Int -> b
nth l m = let f x g 0 = x
f x g i = g (i - 1)
fail _ = error "(!!){PreludeList}: index too large"
in foldr f fail l m
{-# nth :: Inline #-}
--nth _ n | n < 0 = error "(!!){PreludeList}: negative index"
--nth [] n = error "(!!){PreludeList}: index too large"
--nth (x:xs) n
-- | n == 0 = x
-- | otherwise = nth xs (n - 1)
--{-# nth :: Strictness("S,S") #-}
-- map f xs applies f to each element of xs; i.e., map f xs == [f x | x <- xs].
map :: (a -> b) -> [a] -> [b]
map f xs = build (\ c n -> foldr (\ a b -> c (f a) b) n xs)
--map f [] = []
--map f (x:xs) = f x : map f xs
{-# map :: Inline #-}
-- filter, applied to a predicate and a list, returns the list of those
-- elements that satisfy the predicate; i.e.,
-- filter p xs == [x | x <- xs, p x].
filter :: (a -> Bool) -> [a] -> [a]
filter f xs = build (\ c n ->
foldr (\ a b -> if f a then c a b else b)
n xs)
--filter p = foldr (\x xs -> if p x then x:xs else xs) []
{-# filter :: Inline #-}
-- partition takes a predicate and a list and returns a pair of lists:
-- those elements of the argument list that do and do not satisfy the
-- predicate, respectively; i.e.,
-- partition p xs == (filter p xs, filter (not . p) xs).
partition :: (a -> Bool) -> [a] -> ([a],[a])
partition p = foldr select ([],[])
where select x (ts,fs) | p x = (x:ts,fs)
| otherwise = (ts,x:fs)
{-# partition :: Inline #-}
-- foldl, applied to a binary operator, a starting value (typically the
-- left-identity of the operator), and a list, reduces the list using
-- the binary operator, from left to right:
-- foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn
-- foldl1 is a variant that has no starting value argument, and thus must
-- be applied to non-empty lists. scanl is similar to foldl, but returns
-- a list of successive reduced values from the left:
-- scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
-- Note that last (scanl f z xs) == foldl f z xs.
-- scanl1 is similar, again without the starting element:
-- scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f z xs = foldr (\ b g a -> g (f a b)) id xs z
--foldl f z [] = z
--foldl f z (x:xs) = foldl f (f z x) xs
{-# foldl :: Inline #-}
foldl1 :: (a -> a -> a) -> [a] -> a
foldl1 f (x:xs) = foldl f x xs
foldl1 _ [] = error "foldl1{PreludeList}: empty list"
{-# foldl1 :: Inline #-}
scanl :: (a -> b -> a) -> a -> [b] -> [a]
scanl f q xs = q : (case xs of
[] -> []
x:xs -> scanl f (f q x) xs)
{-# scanl :: Inline #-}
scanl1 :: (a -> a -> a) -> [a] -> [a]
scanl1 f (x:xs) = scanl f x xs
scanl1 _ [] = error "scanl1{PreludeList}: empty list"
{-# scanl1 :: Inline #-}
-- foldr, foldr1, scanr, and scanr1 are the right-to-left duals of the
-- above functions.
--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 "foldr1{PreludeList}: empty list"
{-# foldr1 :: Inline #-}
-- I'm not sure the build/foldr expansion wins.
scanr :: (a -> b -> b) -> b -> [a] -> [b]
--scanr f q0 l = build (\ c n ->
-- let g x qs@(q:_) = c (f x q) qs
-- in foldr g (c q0 n) l)
scanr f q0 [] = [q0]
scanr f q0 (x:xs) = f x q : qs
where qs@(q:_) = scanr f q0 xs
{-# scanr :: Inline #-}
scanr1 :: (a -> a -> a) -> [a] -> [a]
scanr1 f [x] = [x]
scanr1 f (x:xs) = f x q : qs
where qs@(q:_) = scanr1 f xs
scanr1 _ [] = error "scanr1{PreludeList}: empty list"
{-# scanr1 :: Inline #-}
-- iterate f x returns an infinite list of repeated applications of f to x:
-- iterate f x == [x, f x, f (f x), ...]
iterate :: (a -> a) -> a -> [a]
iterate f x = build (\ c n ->
let iterate' x' = c x' (iterate' (f x'))
in iterate' x)
--iterate f x = x : iterate f (f x)
{-# iterate :: Inline #-}
-- repeat x is an infinite list, with x the value of every element.
repeat :: a -> [a]
repeat x = build (\ c n -> let r = c x r in r)
--repeat x = xs where xs = x:xs
{-# repeat :: Inline #-}
-- cycle ties a finite list into a circular one, or equivalently,
-- the infinite repetition of the original list. It is the identity
-- on infinite lists.
cycle :: [a] -> [a]
cycle xs = xs' where xs' = xs ++ xs'
-- take n, applied to a list xs, returns the prefix of xs of length n,
-- or xs itself if n > length xs. drop n xs returns the suffix of xs
-- after the first n elements, or [] if n > length xs. splitAt n xs
-- is equivalent to (take n xs, drop n xs).
take :: (Integral a) => a -> [b] -> [b]
take n l = takeInt (fromIntegral n) l
{-# take :: Inline #-}
takeInt :: Int -> [b] -> [b]
takeInt m l =
build (\ c n ->
let f x g i | i <= 0 = n
| otherwise = c x (g (i - 1))
in foldr f (\ _ -> n) l m)
--takeInt 0 _ = []
--takeInt _ [] = []
--takeInt n l | n > 0 = primTake n l
{-# takeInt :: Inline #-}
-- Writing drop and friends in terms of build/foldr seems to lose
-- way big since they cause an extra traversal of the list tail
-- (except when the calls are being deforested).
drop :: (Integral a) => a -> [b] -> [b]
drop n l = dropInt (fromIntegral n) l
{-# drop :: Inline #-}
{-# drop :: Strictness("S,S") #-}
dropInt :: Int -> [b] -> [b]
dropInt 0 xs = xs
dropInt _ [] = []
dropInt (n+1) (_:xs) = dropInt n xs
{-# dropInt :: Inline #-}
splitAt :: (Integral a) => a -> [b] -> ([b],[b])
splitAt n l = splitAtInt (fromIntegral n) l
{-# splitAt :: Inline #-}
splitAtInt :: Int -> [b] -> ([b],[b])
splitAtInt 0 xs = ([],xs)
splitAtInt _ [] = ([],[])
splitAtInt (n+1) (x:xs) = (x:xs',xs'') where (xs',xs'') = splitAtInt n xs
{-# splitAtInt :: Inline #-}
-- takeWhile, applied to a predicate p and a list xs, returns the longest
-- prefix (possibly empty) of xs of elements that satisfy p. dropWhile p xs
-- returns the remaining suffix. Span p xs is equivalent to
-- (takeWhile p xs, dropWhile p xs), while break p uses the negation of p.
takeWhile :: (a -> Bool) -> [a] -> [a]
takeWhile p l = build (\ c n -> foldr (\ a b -> if p a then c a b else n) n l)
--takeWhile p [] = []
--takeWhile p (x:xs)
-- | p x = x : takeWhile p xs
-- | otherwise = []
{-# takeWhile :: Inline #-}
dropWhile :: (a -> Bool) -> [a] -> [a]
dropWhile p [] = []
dropWhile p xs@(x:xs')
| p x = dropWhile p xs'
| otherwise = xs
{-# dropWhile :: Inline #-}
span, break :: (a -> Bool) -> [a] -> ([a],[a])
span p [] = ([],[])
span p xs@(x:xs')
| p x = let (ys,zs) = span p xs' in (x:ys,zs)
| otherwise = ([],xs)
break p = span (not . p)
{-# span :: Inline #-}
{-# break :: Inline #-}
-- lines breaks a string up into a list of strings at newline characters.
-- The resulting strings do not contain newlines. Similary, words
-- breaks a string up into a list of words, which were delimited by
-- white space. unlines and unwords are the inverse operations.
-- unlines joins lines with terminating newlines, and unwords joins
-- words with separating spaces.
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 isSpace s of
"" -> []
s' -> w : words s''
where (w, s'') = break isSpace s'
unlines :: [String] -> String
unlines = concat . map (++ "\n")
{-# unlines :: Inline #-}
unwords :: [String] -> String
unwords [] = ""
unwords ws = foldr1 (\w s -> w ++ ' ':s) ws
-- nub (meaning "essence") removes duplicate elements from its list argument.
nub :: (Eq a) => [a] -> [a]
nub l = build (\ c n ->
let f x g [] = c x (g [x])
f x g xs = if elem x xs
then (g xs)
else c x (g (x:xs))
in foldr f (\ _ -> n) l [])
{-# nub :: Inline #-}
--nub [] = []
--nub (x:xs) = x : nub (filter (/= x) xs)
-- reverse xs returns the elements of xs in reverse order. xs must be finite.
reverse :: [a] -> [a]
reverse l = build (\ c n ->
let f x g tail = g (c x tail)
in foldr f id l n)
{-# reverse :: Inline #-}
--reverse x = reverse1 x [] where
-- reverse1 [] a = a
-- reverse1 (x:xs) a = reverse1 xs (x:a)
-- and returns the conjunction of a Boolean list. For the result to be
-- True, the list must be finite; False, however, results from a False
-- value at a finite index of a finite or infinite list. or is the
-- disjunctive dual of and.
and, or :: [Bool] -> Bool
and = foldr (&&) True
or = foldr (||) False
{-# and :: Inline #-}
{-# or :: Inline #-}
-- Applied to a predicate and a list, any determines if any element
-- of the list satisfies the predicate. Similarly, for all.
any, all :: (a -> Bool) -> [a] -> Bool
any p = or . map p
all p = and . map p
{-# any :: Inline #-}
{-# all :: Inline #-}
-- elem is the list membership predicate, usually written in infix form,
-- e.g., x `elem` xs. notElem is the negation.
elem, notElem :: (Eq a) => a -> [a] -> Bool
elem x ys = foldr (\ y t -> (x == y) || t) False ys
--x `elem` [] = False
--x `elem` (y:ys) = x == y || x `elem` ys
{-# elem :: Inline #-}
notElem x y = not (x `elem` y)
-- sum and product compute the sum or product of a finite list of numbers.
sum, product :: (Num a) => [a] -> a
sum = foldl (+) 0
product = foldl (*) 1
{-# sum :: Inline #-}
{-# product :: Inline #-}
-- sums and products give a list of running sums or products from
-- a list of numbers. For example, sums [1,2,3] == [0,1,3,6].
sums, products :: (Num a) => [a] -> [a]
sums = scanl (+) 0
products = scanl (*) 1
-- maximum and minimum return the maximum or minimum value from a list,
-- which must be non-empty, finite, and of an ordered type.
maximum, minimum :: (Ord a) => [a] -> a
maximum = foldl1 max
minimum = foldl1 min
{-# maximum :: Inline #-}
{-# minimum :: Inline #-}
-- concat, applied to a list of lists, returns their flattened concatenation.
concat :: [[a]] -> [a]
concat xs = build (\ c n -> foldr (\ x y -> foldr c y x) n xs)
--concat [] = []
--concat (l:ls) = l ++ concat ls
{-# concat :: Inline #-}
-- transpose, applied to a list of lists, returns that list with the
-- "rows" and "columns" interchanged. The input need not be rectangular
-- (a list of equal-length lists) to be completely transposable, but can
-- be "triangular": Each successive component list must be not longer
-- than the previous one; any elements outside of the "triangular"
-- transposable region are lost. The input can be infinite in either
-- dimension or both.
transpose :: [[a]] -> [[a]]
transpose = foldr
(\xs xss -> zipWith (:) xs (xss ++ repeat []))
[]
{-# transpose :: Inline #-}
-- zip takes two lists and returns a list of corresponding pairs. If one
-- input list is short, excess elements of the longer list are discarded.
-- zip3 takes three lists and returns a list of triples, etc. Versions
-- of zip producing up to septuplets are defined here.
zip :: [a] -> [b] -> [(a,b)]
zip = zipWith (\a b -> (a,b))
{-# zip :: Inline #-}
zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]
zip3 = zipWith3 (\a b c -> (a,b,c))
{-# zip3 :: Inline #-}
zip4 :: [a] -> [b] -> [c] -> [d] -> [(a,b,c,d)]
zip4 = zipWith4 (\a b c d -> (a,b,c,d))
{-# zip4 :: Inline #-}
zip5 :: [a] -> [b] -> [c] -> [d] -> [e] -> [(a,b,c,d,e)]
zip5 = zipWith5 (\a b c d e -> (a,b,c,d,e))
{-# zip5 :: Inline #-}
zip6 :: [a] -> [b] -> [c] -> [d] -> [e] -> [f]
-> [(a,b,c,d,e,f)]
zip6 = zipWith6 (\a b c d e f -> (a,b,c,d,e,f))
{-# zip6 :: Inline #-}
zip7 :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g]
-> [(a,b,c,d,e,f,g)]
zip7 = zipWith7 (\a b c d e f g -> (a,b,c,d,e,f,g))
{-# zip7 :: Inline #-}
-- The zipWith family generalises the zip family by zipping with the
-- function given as the first argument, instead of a tupling function.
-- For example, zipWith (+) is applied to two lists to produce the list
-- of corresponding sums.
zipWith :: (a->b->c) -> [a]->[b]->[c]
zipWith z as bs =
build (\ c' n' ->
let f' a g' (b:bs) = c' (z a b) (g' bs)
f' a g' _ = n'
in foldr f' (\ _ -> n') as bs)
--zipWith z (a:as) (b:bs) = z a b : zipWith z as bs
--zipWith _ _ _ = []
{-# zipWith :: Inline #-}
zipWith3 :: (a->b->c->d) -> [a]->[b]->[c]->[d]
zipWith3 z as bs cs =
build (\ c' n' ->
let f' a g' (b:bs) (c:cs) = c' (z a b c) (g' bs cs)
f' a g' _ _ = n'
in foldr f' (\ _ _ -> n') as bs cs)
{-# zipWith3 :: Inline #-}
--zipWith3 z (a:as) (b:bs) (c:cs)
-- = z a b c : zipWith3 z as bs cs
--zipWith3 _ _ _ _ = []
zipWith4 :: (a->b->c->d->e) -> [a]->[b]->[c]->[d]->[e]
zipWith4 z as bs cs ds =
build (\ c' n' ->
let f' a g' (b:bs) (c:cs) (d:ds) = c' (z a b c d) (g' bs cs ds)
f' a g' _ _ _ = n'
in foldr f' (\ _ _ _ -> n') as bs cs ds)
{-# zipWith4 :: Inline #-}
--zipWith4 z (a:as) (b:bs) (c:cs) (d:ds)
-- = z a b c d : zipWith4 z as bs cs ds
--zipWith4 _ _ _ _ _ = []
zipWith5 :: (a->b->c->d->e->f)
-> [a]->[b]->[c]->[d]->[e]->[f]
zipWith5 z as bs cs ds es=
build (\ c' n' ->
let f' a g' (b:bs) (c:cs) (d:ds) (e:es) =
c' (z a b c d e) (g' bs cs ds es)
f' a g' _ _ _ _ = n'
in foldr f' (\ _ _ _ _ -> n') as bs cs ds es)
{-# zipWith5 :: Inline #-}
--zipWith5 z (a:as) (b:bs) (c:cs) (d:ds) (e:es)
-- = z a b c d e : zipWith5 z as bs cs ds es
--zipWith5 _ _ _ _ _ _ = []
zipWith6 :: (a->b->c->d->e->f->g)
-> [a]->[b]->[c]->[d]->[e]->[f]->[g]
zipWith6 z as bs cs ds es fs =
build (\ c' n' ->
let f' a g' (b:bs) (c:cs) (d:ds) (e:es) (f:fs) =
c' (z a b c d e f) (g' bs cs ds es fs)
f' a g' _ _ _ _ _ = n'
in foldr f' (\ _ _ _ _ _ -> n') as bs cs ds es fs)
{-# zipWith6 :: Inline #-}
--zipWith6 z (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs)
-- = z a b c d e f : zipWith6 z as bs cs ds es fs
--zipWith6 _ _ _ _ _ _ _ = []
zipWith7 :: (a->b->c->d->e->f->g->h)
-> [a]->[b]->[c]->[d]->[e]->[f]->[g]->[h]
zipWith7 z as bs cs ds es fs gs =
build (\ c' n' ->
let f' a g' (b:bs) (c:cs) (d:ds) (e:es) (f:fs) (g:gs) =
c' (z a b c d e f g) (g' bs cs ds es fs gs)
f' a g' _ _ _ _ _ _ = n'
in foldr f' (\ _ _ _ _ _ _ -> n') as bs cs ds es fs gs)
{-# zipWith7 :: Inline #-}
--zipWith7 z (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs) (g:gs)
-- = z a b c d e f g : zipWith7 z as bs cs ds es fs gs
--zipWith7 _ _ _ _ _ _ _ _ = []
-- unzip transforms a list of pairs into a pair of lists. As with zip,
-- a family of such functions up to septuplets is provided.
unzip :: [(a,b)] -> ([a],[b])
unzip = foldr (\(a,b) ~(as,bs) -> (a:as,b:bs)) ([],[])
{-# unzip :: Inline #-}
unzip3 :: [(a,b,c)] -> ([a],[b],[c])
unzip3 = foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))
([],[],[])
{-# unzip3 :: Inline #-}
unzip4 :: [(a,b,c,d)] -> ([a],[b],[c],[d])
unzip4 = foldr (\(a,b,c,d) ~(as,bs,cs,ds) ->
(a:as,b:bs,c:cs,d:ds))
([],[],[],[])
{-# unzip4 :: Inline #-}
unzip5 :: [(a,b,c,d,e)] -> ([a],[b],[c],[d],[e])
unzip5 = foldr (\(a,b,c,d,e) ~(as,bs,cs,ds,es) ->
(a:as,b:bs,c:cs,d:ds,e:es))
([],[],[],[],[])
{-# unzip5 :: Inline #-}
unzip6 :: [(a,b,c,d,e,f)] -> ([a],[b],[c],[d],[e],[f])
unzip6 = foldr (\(a,b,c,d,e,f) ~(as,bs,cs,ds,es,fs) ->
(a:as,b:bs,c:cs,d:ds,e:es,f:fs))
([],[],[],[],[],[])
{-# unzip6 :: Inline #-}
unzip7 :: [(a,b,c,d,e,f,g)] -> ([a],[b],[c],[d],[e],[f],[g])
unzip7 = foldr (\(a,b,c,d,e,f,g) ~(as,bs,cs,ds,es,fs,gs) ->
(a:as,b:bs,c:cs,d:ds,e:es,f:fs,g:gs))
([],[],[],[],[],[],[])
{-# unzip7 :: Inline #-}
|