summaryrefslogtreecommitdiff
path: root/progs/prelude/PreludeList.hs
diff options
context:
space:
mode:
Diffstat (limited to 'progs/prelude/PreludeList.hs')
-rw-r--r--progs/prelude/PreludeList.hs585
1 files changed, 585 insertions, 0 deletions
diff --git a/progs/prelude/PreludeList.hs b/progs/prelude/PreludeList.hs
new file mode 100644
index 0000000..3e445c3
--- /dev/null
+++ b/progs/prelude/PreludeList.hs
@@ -0,0 +1,585 @@
+-- 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 #-}
+