list-extras 0.4.1.4 → 0.4.1.6
raw patch · 14 files changed
+642/−623 lines, 14 filessetup-changednew-uploader
Files
- CHANGELOG +5/−0
- Data/List/Extras.hs +0/−37
- Data/List/Extras/Argmax.hs +0/−204
- Data/List/Extras/LazyLength.hs +0/−145
- Data/List/Extras/Pair.hs +0/−136
- Prelude/Listless.hs +0/−58
- README.md +32/−0
- Setup.hs +0/−30
- list-extras.cabal +25/−13
- src/Data/List/Extras.hs +37/−0
- src/Data/List/Extras/Argmax.hs +204/−0
- src/Data/List/Extras/LazyLength.hs +145/−0
- src/Data/List/Extras/Pair.hs +136/−0
- src/Prelude/Listless.hs +58/−0
CHANGELOG view
@@ -1,3 +1,8 @@+0.4.1.6 (2021-10-17):+ - Updating maintainer's email, url, etc+ - Set up GithubActions for CI.+0.4.1.4 (2015-05-30):+ - Moved VERSION to CHANGELOG 0.4.1 (2012-09-26): - Prelude.Listless: Guarded re-export of Prelude.catch with CPP 0.4.0.1 (2010-05-31):
− Data/List/Extras.hs
@@ -1,37 +0,0 @@-{-# OPTIONS_GHC -Wall -fwarn-tabs #-}-------------------------------------------------------------------- ~ 2010.04.05--- |--- Module : Data.List.Extras--- Copyright : Copyright (c) 2007--2015 wren gayle romano--- License : BSD3--- Maintainer : wren@community.haskell.org--- Stability : stable--- Portability : Haskell98------ This module provides a single header for all @Data.List.Extras.*@--- modules and provides a small number of other utility functions.-------------------------------------------------------------------module Data.List.Extras- (- list- , module Data.List.Extras.LazyLength- , module Data.List.Extras.Pair- , module Data.List.Extras.Argmax- ) where--import Data.List.Extras.LazyLength-import Data.List.Extras.Pair-import Data.List.Extras.Argmax---- | Pattern matching for lists, as a first-class function. (Could--- also be considered as a non-recursive 'foldr'.) If the list--- argument is @[]@ then the default argument is returned; otherwise--- the function is called with the head and tail of the list.-list :: (a -> [a] -> b) -> b -> [a] -> b-list _ z [] = z-list f _ (x:xs) = f x xs------------------------------------------------------------------------------------------------------------------------------ fin.
− Data/List/Extras/Argmax.hs
@@ -1,204 +0,0 @@-{-# OPTIONS_GHC -Wall -fwarn-tabs #-}-------------------------------------------------------------------- ~ 2010.10.15--- |--- Module : Data.List.Extras.ArgMax--- Copyright : Copyright (c) 2007--2015 wren gayle romano--- License : BSD3--- Maintainer : wren@community.haskell.org--- Stability : experimental--- Portability : Haskell98------ This module provides variants of the 'maximum' and 'minimum'--- functions which return the elements for which some function is--- maximized or minimized.-------------------------------------------------------------------module Data.List.Extras.Argmax- (- -- * Utility functions- catchNull- - -- * Generic versions- , argmaxBy, argmaxesBy, argmaxWithMaxBy, argmaxesWithMaxBy- - -- * Maximum variations- , argmax, argmaxes, argmaxWithMax, argmaxesWithMax- - -- * Minimum variations- , argmin, argmins, argminWithMin, argminsWithMin- - {- TODO: CPS and monadic variants; argmax2, argmax3,... -}- {- TODO: make sure argmax et al are "good consumers" for fusion -}- ) where--- argmaxM :: (Monad m, Ord b) => (a -> m b) -> [a] -> m (Maybe a)--import Data.List (foldl')--------------------------------------------------------------------------------------------------------------------------------------- | Apply a list function safely, i.e. when the list is non-empty.--- All other functions will throw errors on empty lists, so use--- this to make your own safe variations.-catchNull :: ([a] -> b) -> ([a] -> Maybe b)-{-# INLINE catchNull #-}--- We use the explicit lambda in order to improve inlining in ghc-7.-catchNull f = \xs ->- case xs of- [] -> Nothing- _:_ -> Just (f xs)----- | Minimize the number of string literals-emptyListError :: String -> a-{-# NOINLINE emptyListError #-}-emptyListError fun =- error $ "Data.List.Extras.Argmax."++fun++": empty list"----- | Apply a list function unsafely. For internal use.-throwNull :: String -> (a -> [a] -> b) -> ([a] -> b)-{-# INLINE throwNull #-}--- We use the explicit lambda in order to improve inlining in ghc-7.-throwNull fun f = \xs ->- case xs of- [] -> emptyListError fun- x:xs' -> f x xs'-------------------------------------------------------------------------------------------------------------------------------------- | Tail-recursive driver-_argmaxWithMaxBy :: (b -> b -> Bool) -> (a -> b) -> a -> [a] -> (a,b)-{-# INLINE _argmaxWithMaxBy #-}--- We use the explicit lambda in order to improve inlining in ghc-7.-_argmaxWithMaxBy isBetterThan f =- \x xs -> foldl' cmp (x, f x) xs- where- cmp bfb@(_,fb) a =- let fa = f a in- if fa `isBetterThan` fb- then (a,fa)- else bfb----- | Tail-recursive driver-_argmaxesWithMaxBy :: (b -> b -> Ordering) -> (a -> b) -> a -> [a] -> ([a],b)-{-# INLINE _argmaxesWithMaxBy #-}--- We use the explicit lambda in order to improve inlining in ghc-7.-_argmaxesWithMaxBy isBetterEqualThan f =- \x xs -> foldl' cmp ([x], f x) xs- where- cmp bsfb@(bs,fb) a =- let fa = f a in- case isBetterEqualThan fa fb of- GT -> ([a], fa)- EQ -> (a:bs, fb)- _ -> bsfb---_argmaxBy :: (b -> b -> Bool) -> (a -> b) -> a -> [a] -> a-{-# INLINE _argmaxBy #-}--- We use the point-free style in order to improve inlining in ghc-7.-_argmaxBy k f = (fst .) . _argmaxWithMaxBy k f---_argmaxesBy :: (b -> b -> Ordering) -> (a -> b) -> a -> [a] -> [a]-{-# INLINE _argmaxesBy #-}--- We use the point-free style in order to improve inlining in ghc-7.-_argmaxesBy k f = (fst .) . _argmaxesWithMaxBy k f-------------------------------------------------------------------------------------------------------------------------------------bool :: (a -> a -> Ordering) -> (a -> a -> Bool)-bool ord = \a b -> ord a b == GT----- | Return an element of the list which maximizes the function--- according to a user-defined ordering.-argmaxBy :: (b -> b -> Ordering) -> (a -> b) -> [a] -> a-argmaxBy ord f = throwNull "argmaxBy"- $ _argmaxBy (bool ord) f----- | Return all elements of the list which maximize the function--- according to a user-defined ordering.-argmaxesBy :: (b -> b -> Ordering) -> (a -> b) -> [a] -> [a]-argmaxesBy ord f = throwNull "argmaxesBy"- $ _argmaxesBy ord f----- | Return an element of the list which maximizes the function--- according to a user-defined ordering, and return the value of--- the function at that element as well.-argmaxWithMaxBy :: (b -> b -> Ordering) -> (a -> b) -> [a] -> (a, b)-argmaxWithMaxBy ord f = throwNull "argmaxWithMaxBy" - $ _argmaxWithMaxBy (bool ord) f----- | Return all elements of the list which maximize the function--- according to a user-defined ordering, and return the value of--- the function at those elements as well.-argmaxesWithMaxBy :: (b -> b -> Ordering) -> (a -> b) -> [a] -> ([a], b)-argmaxesWithMaxBy ord f = throwNull "argmaxesWithMaxBy"- $ _argmaxesWithMaxBy ord f--------------------------------------------------------------------- SPECIALIZE on b \in {Int,Integer,Float,Double} for the four--- functions below nearly doubles the library size (about +21kB).--- For a basic utility library that's a bit excessive, though if--- we break the argmax stuff out from list-extras then we might go--- through with it for performance sake.---- | Return an element of the list which maximizes the function.-argmax :: (Ord b) => (a -> b) -> [a] -> a-argmax f = throwNull "argmax"- $ _argmaxBy (>) f---- | Return all elements of the list which maximize the function.-argmaxes :: (Ord b) => (a -> b) -> [a] -> [a]-argmaxes f = throwNull "argmaxes"- $ _argmaxesBy compare f----- | Return an element of the list which maximizes the function,--- and return the value of the function at that element as well.-argmaxWithMax :: (Ord b) => (a -> b) -> [a] -> (a, b)-argmaxWithMax f = throwNull "argmaxWithMax" - $ _argmaxWithMaxBy (>) f----- | Return all elements of the list which maximize the function,--- and return the value of the function at those elements as well.-argmaxesWithMax :: (Ord b) => (a -> b) -> [a] -> ([a], b)-argmaxesWithMax f = throwNull "argmaxesWithMax"- $ _argmaxesWithMaxBy compare f---------------------------------------------------------------------- | Return an element of the list which minimizes the function.-argmin :: (Ord b) => (a -> b) -> [a] -> a-argmin f = throwNull "argmax"- $ _argmaxBy (<) f---- | Return all elements of the list which minimize the function.-argmins :: (Ord b) => (a -> b) -> [a] -> [a]-argmins f = throwNull "argmins"- $ _argmaxesBy (flip compare) f----- | Return an element of the list which minimizes the function,--- and return the value of the function at that element as well.-argminWithMin :: (Ord b) => (a -> b) -> [a] -> (a, b)-argminWithMin f = throwNull "argminWithMin"- $ _argmaxWithMaxBy (<) f---- | Return all elements of the list which minimize the function,--- and return the value of the function at those elements as well.-argminsWithMin :: (Ord b) => (a -> b) -> [a] -> ([a], b)-argminsWithMin f = throwNull "argminsWithMin"- $ _argmaxesWithMaxBy (flip compare) f------------------------------------------------------------------------------------------------------------------------------ fin.
− Data/List/Extras/LazyLength.hs
@@ -1,145 +0,0 @@---- 2008.10.12: GHC 6.10 breaks -fno-warn-orphans so that it no--- longer suppresses the warnings for orphaned RULES. Hence -Werror--- will make things crash on those systems, and even if that's--- removed then -Wall will send up too many false positives which--- may disconcert users.-{-# OPTIONS_GHC -Wall -fwarn-tabs #-}---- Unfortunately GHC < 6.10 needs -fglasgow-exts in order to actually--- parse RULES (see -ddump-rules); the -frewrite-rules flag only--- enables the application of rules, instead of doing what we want.--- Apparently this is fixed in 6.10.------ http://hackage.haskell.org/trac/ghc/ticket/2213--- http://www.mail-archive.com/glasgow-haskell-users@haskell.org/msg14313.html--- OPTIONS_GHC -O2 -fglasgow-exts -frewrite-rules--------------------------------------------------------------------- ~ 2009.04.02--- |--- Module : Data.List.Extras.LazyLength--- Copyright : Copyright (c) 2007--2015 wren gayle romano--- License : BSD3--- Maintainer : wren@community.haskell.org--- Stability : stable--- Portability : Haskell98------ This module provides least-strict functions for getting a list's--- length and doing natural things with it.------ The regular version of @length@ will traverse the entire spine--- of the list in order to return an answer. For comparing the--- length against some bound, that is by far too strict. Being too--- strict can cause a space leak by expanding a lazy list before--- necessary (or more than is ever necessary). And it can lead to--- unnecessarily non-terminating programs when trying to determine--- if an infinite list is longer or shorter than some finite bound.------ A nicer version of @length@ would return some lazy approximation--- of an answer which retains the proper semantics. An option for--- doing this is to return Peano integers which can be decremented--- as much as necessary and no further (i.e. at most one more than--- the bound). Of course, Peano integers are woefully inefficient.--- This module provides functions with the same lazy effect but--- does so efficiently instead.------ As of version 0.3.0 the GHC rules to automatically rewrite--- certain calls to 'length' into our least-strict versions have--- been /removed/ for more consistent and predictable semantics.--- All clients should explicitly call these least-strict functions--- if they want the least-strict behavior.-------------------------------------------------------------------module Data.List.Extras.LazyLength- ( lengthBound, lengthCompare- ) where--------------------------------------------------------------------------------------------------------------------------------------- | A variant of 'length' which is least-strict for comparing--- against a boundary length.------ @lengthBound@ is polymorphic in the return of the helper--- function so we can use 'compare' as well as '>', '>=', '==',--- '/=', '<=', '<'. If you want to use any other functions, know--- that we only preserve the ordering of the list's length vs the--- boundary length and so the function should not rely on the true--- values of either of the numbers being compared.--lengthBound :: Int -> (Int -> Int -> a) -> [b] -> a-lengthBound n cmp xs- | n < 0 = case xs of- [] -> cmp n 0- (_:_) -> cmp n 1- | otherwise = go n xs- where- go n' [] = cmp n' 0- go 0 (_:_) = cmp 0 1- go n' (_:xs') = (go $! n'-1) xs'--{- bad RULES--- The rules themselves are correct but they alter program semantics--- regarding bottoms, depending on whether they fire or not.--"lengthBound/(>)" forall n xs. n > length xs = lengthBound n (>) xs-"lengthBound/(>=)" forall n xs. n >= length xs = lengthBound n (>=) xs-"lengthBound/(==)" forall n xs. n == length xs = lengthBound n (==) xs-"lengthBound/(/=)" forall n xs. n /= length xs = lengthBound n (/=) xs-"lengthBound/(<=)" forall n xs. n <= length xs = lengthBound n (<=) xs-"lengthBound/(<)" forall n xs. n < length xs = lengthBound n (<) xs-"lengthBound/compare" forall n xs.- compare n (length xs) = lengthBound n compare xs--"lengthBound\\(>)" forall n xs. length xs > n = lengthBound n (<) xs-"lengthBound\\(>=)" forall n xs. length xs >= n = lengthBound n (<=) xs-"lengthBound\\(==)" forall n xs. length xs == n = lengthBound n (==) xs-"lengthBound\\(/=)" forall n xs. length xs /= n = lengthBound n (/=) xs-"lengthBound\\(<=)" forall n xs. length xs <= n = lengthBound n (>=) xs-"lengthBound\\(<)" forall n xs. length xs < n = lengthBound n (>) xs-"lengthBound\\compare" forall n xs.- compare (length xs) n = lengthBound n (flip compare) xs- -}--------------------------------------------------------------------------------------------------------------------------------------- | A variant of 'length' which is least-strict for comparing--- the lengths of two lists. This is as strict as the length of the--- shorter list (which allows comparing an infinite list against a--- finite list).------ If you're going to immediately follow this with a 'zip' function--- then see "Data.List.Extras.Pair" instead.--lengthCompare :: [a] -> [b] -> Ordering-lengthCompare [] [] = EQ-lengthCompare (_:_) [] = GT-lengthCompare [] (_:_) = LT-lengthCompare (_:xs) (_:ys) = lengthCompare xs ys---{- bad RULES--- The rules themselves are correct but they alter program semantics--- regarding bottoms, depending on whether they fire or not.--"lengthCompare/(>)" forall xs ys.- length xs > length ys = lengthCompare xs ys == GT-"lengthCompare/(>=)" forall xs ys.- length xs >= length ys = lengthCompare xs ys /= LT-"lengthCompare/(==)" forall xs ys.- length xs == length ys = lengthCompare xs ys == EQ-"lengthCompare/(/=)" forall xs ys.- length xs /= length ys = lengthCompare xs ys /= EQ-"lengthCompare/(<=)" forall xs ys.- length xs <= length ys = lengthCompare xs ys /= GT-"lengthCompare/(<)" forall xs ys.- length xs < length ys = lengthCompare xs ys == LT--"lengthCompare/compare" forall xs ys.- compare (length xs) (length ys) = lengthCompare xs ys- -}------------------------------------------------------------------------------------------------------------------------------ fin.
− Data/List/Extras/Pair.hs
@@ -1,136 +0,0 @@-{-# OPTIONS_GHC -Wall -fwarn-tabs #-}-------------------------------------------------------------------- ~ 2010.11.15--- |--- Module : Data.List.Extras.Pair--- Copyright : Copyright (c) 2007--2015 wren gayle romano--- License : BSD3--- Maintainer : wren@community.haskell.org--- Stability : stable--- Portability : Haskell98------ This module provides safe zipping functions which will fail--- (return 'Nothing') on uneven length lists.-------------------------------------------------------------------module Data.List.Extras.Pair- (- -- * Safe functions for zipping lists- pairWithBy, pairWith, pairBy, pair- - -- * Special safe zipping functions- , biject, biject'- - -- * New (unsafe) zipping functions- , zipWithBy, zipBy- ) where--------------------------------------------------------------------------------------------------------------------------------------- TODO: benchmark fusion performance of:------ foldr cons nil .: zipWith (,)--- zipWithBy (,) cons nil------ ...That is, the latter is a manual fusion of the former, but--- does zip/zipWith have a special ability to fuse with the incoming--- lists? Or can foldr fuse with consumers in ways zipWithBy can't?---- | An unsafe variant of 'pairWithBy' to fill out the interface.-zipWithBy :: (a -> b -> c) -- tuple homomorphism- -> (c -> d -> d) -> d -- list homomorphism- -> [a] -> [b] -> d -- a @zip@ function-{-# INLINE zipWithBy #-}--- We use the explicit lambda in order to improve inlining in ghc-7.-zipWithBy k f z = \xs ys -> zipWB xs ys id- where- zipWB (x:xs) (y:ys) cc = zipWB xs ys (cc . f (k x y))- zipWB _ _ cc = cc z----- | A version of 'zip' that uses a user-defined list homomorphism.-zipBy :: ((a,b) -> d -> d) -> d -> [a] -> [b] -> d-{-# INLINE zipBy #-}-zipBy = zipWithBy (,)--------------------------------------------------------------------------------------------------------------------------------------- | A generic version of 'pair'. The first argument is a tuple--- homomorphism (i.e. a function for how to combine values from the--- two lists), the second two arguments form a list homomorphism--- (i.e. so you can 'foldr' the @[c]@ list directly without actually--- constructing it).------ In order to evaluate to WHNF 'pairWithBy' is strict in both list--- arguments, as it must be, to determine that the lists are of the--- same length. This means it can survive one infinite list (yielding--- 'Nothing') but that it can't survive two. The implementation is--- very efficient and uses a tight tail-recursive loop, however--- with extremely long lists it will be churning through heap and--- that tightness can make it hard to interrupt (lists of 1 million--- elements return in 1~2 seconds, but lists of 10 million can lock--- your system up).--pairWithBy :: (a -> b -> c) -- @(,)@ tuple homomorphism- -> (c -> d -> d) -- @(:)@ list homomorphism, pt. 1- -> d -- @[]@ list homomorphism, pt. 2- -> [a] -> [b] -> Maybe d -- a safer @zip@ function-{-# INLINE pairWithBy #-}--- We use the explicit lambda in order to improve inlining in ghc-7.-pairWithBy k f z = \xs ys -> pairWB xs ys id- where- -- N.B. Strict accumulators are usually awesome, but don't- -- even consider it when doing CPS! Making @cc@ strict degrades- -- performance significantly; it takes twice as long and twice- -- as much heap just to get to WHNF. After evaluating the spine- -- of the resulting list from 'pair' that drops to +10% time- -- and +25% heap, which is still much worse.- - pairWB (x:xs) (y:ys) cc = pairWB xs ys (cc . f (k x y))- pairWB [] [] cc = Just (cc z)- pairWB _ _ _ = Nothing---- TODO: we could make this more general still by fusing @f@ and @k@, which we'd often want to do anyways if we're using this full form.---------------------------------------------------------------------- | A safe version of 'zipWith'.-pairWith :: (a -> b -> c) -> [a] -> [b] -> Maybe [c]-{-# INLINE pairWith #-}-pairWith f = pairWithBy f (:) []----- | A safe version of 'zip' that uses a user-defined list homomorphism.-pairBy :: ((a,b) -> d -> d) -> d -> [a] -> [b] -> Maybe d-{-# INLINE pairBy #-}-pairBy = pairWithBy (,)----- | A safe version of 'zip'.-pair :: [a] -> [b] -> Maybe [(a,b)]-{-# INLINE pair #-}-pair = pairWithBy (,) (:) []---------------------------------------------------------------------- These two are just here because they're often requested, and--- besides they're kinda cute.---- | A bijection from a list of functions and a list of arguments--- to a list of results of applying the functions bijectively.-biject :: [a -> b] -> [a] -> Maybe [b]-{-# INLINE biject #-}-biject = pairWith ($) -- 'id' also works----- | A version of 'biject' that applies functions strictly. N.B.--- the list is still lazily evaluated, this just makes the functions--- strict in their argument.-biject' :: [a -> b] -> [a] -> Maybe [b]-{-# INLINE biject' #-}-biject' = pairWith ($!)------------------------------------------------------------------------------------------------------------------------------ fin.
− Prelude/Listless.hs
@@ -1,58 +0,0 @@-{-# OPTIONS_GHC -Wall -fwarn-tabs #-}-{-# LANGUAGE CPP #-}-------------------------------------------------------------------- ~ 2012.09.26--- |--- Module : Prelude.Listless--- Copyright : Copyright (c) 2007--2015 wren gayle romano--- License : BSD3--- Maintainer : wren@community.haskell.org--- Stability : stable--- Portability : Haskell98 (+CPP)------ This module provides the "Prelude" but removing all the list--- functions. This is helpful for modules that overload those--- function names to work for other types. Note that on GHC 7.6 and--- above @catch@ is no longer exported from the Prelude, and also--- not re-exported from here; whereas, on earlier versions of GHC--- (and non-GHC compilers) we still re-export it.------ Be sure to disable the implicit importing of the prelude when--- you import this one (by passing @-fno-implicit-prelude@ for GHC,--- or by explicitly importing the prelude with an empty import list--- for most implementations).-------------------------------------------------------------------module Prelude.Listless- -- We have to manually specify the exports; can't export @module- -- Prelude@ because that'll export everything and only hide the- -- noted parts from this module, which is meaningless.- (($!), ($), (&&), (.), (=<<), Bool(..), Bounded(..), Char,- Double, Either(..), Enum(..), Eq(..), FilePath, Float, Floating(..),- Fractional(..), Functor(..), IO, IOError, Int, Integer,- Integral(..), Maybe(..), Monad(..), Num(..), Ord(..), Ordering(..),- Rational, Read(..), ReadS, Real(..), RealFloat(..), RealFrac(..),- Show(..), ShowS, String, (^), (^^), appendFile, asTypeOf,-#if __GLASGOW_HASKELL__ < 706- catch,-#endif- const, curry, either, error, even, flip, fromIntegral, fst,- gcd, getChar, getContents, getLine, id, interact, ioError, lcm,- lex, maybe, not, odd, otherwise, print, putChar, putStr, putStrLn,- read, readFile, readIO, readLn, readParen, reads, realToFrac,- seq, showChar, showParen, showString, shows, snd, subtract,- uncurry, undefined, until, userError, writeFile, (||))- - where--import Prelude hiding- ((!!), (++), all, and, any, break, concat, concatMap, cycle,- drop, dropWhile, elem, filter, foldl, foldl1, foldr, foldr1,- head, init, iterate, last, length, lines, lookup, map, mapM,- mapM_, maximum, minimum, notElem, null, or, product, repeat,- replicate, reverse, scanl, scanl1, scanr, scanr1, sequence,- sequence_, span, splitAt, sum, tail, take, takeWhile, unlines,- unwords, unzip, unzip3, words, zip, zip3, zipWith, zipWith3)------------------------------------------------------------------------------------------------------------------------------ fin.
+ README.md view
@@ -0,0 +1,32 @@+list-extras+===========+[](https://hackage.haskell.org/package/list-extras)+[](https://github.com/wrengr/list-extras/actions?query=workflow%3Aci)+[](http://packdeps.haskellers.com/specific?package=list-extras)++The list-extras package provides a few common not-so-common functions+for lists.++## Install++This is a simple package and should be easy to install. You should+be able to use the standard:++ $> cabal install list-extras++## Portability++The implementation is quite portable, relying only on a few basic+language extensions. The complete list of extensions used is:++* CPP+* Rank2Types+* ExistentialQuantification++## Links++* [Website](http://wrengr.org/)+* [Blog](http://winterkoninkje.dreamwidth.org/)+* [Twitter](https://twitter.com/wrengr)+* [Hackage](http://hackage.haskell.org/package/list-extras)+* [GitHub](https://github.com/wrengr/list-extras)
Setup.hs view
@@ -1,37 +1,7 @@ #!/usr/bin/env runhaskell module Main (main) where---- <http://www.haskell.org/ghc/docs/latest/html/libraries/Cabal/Distribution-Simple.html> import Distribution.Simple--{--import Distribution.PackageDescription-import Distribution.Simple.LocalBuildInfo-import System.Exit-import System.Cmd-import System.Directory-import Control.Exception--withCurrentDirectory :: FilePath -> IO a -> IO a-withCurrentDirectory path f = do- cur <- getCurrentDirectory- setCurrentDirectory path- finally f (setCurrentDirectory cur)----- <http://blog.holdenkarau.com/2008/07/integrating-your-hunit-or-other-tests.html>-runTestScript :: Args- -> Bool- -> PackageDescription- -> LocalBuildInfo- -> IO ExitCode-runTestScript args flag pd lbi = withCurrentDirectory "src" (system "make")---main :: IO ()-main = defaultMainWithHooks defaultUserHooks {runTests = runTestScript}--} main :: IO () main = defaultMain
list-extras.cabal view
@@ -1,19 +1,19 @@ ------------------------------------------------------------------- wren gayle romano <wren@community.haskell.org> ~ 2015.05.30+-- wren gayle romano <wren@cpan.org> ~ 2021.10.17 ---------------------------------------------------------------- --- By and large Cabal >=1.2 is fine; but >= 1.6 gives tested-with:--- and source-repository:.-Cabal-Version: >= 1.6+-- Cabal >=1.10 is required by Hackage.+Cabal-Version: >= 1.10 Build-Type: Simple Name: list-extras-Version: 0.4.1.4+Version: 0.4.1.6 Stability: stable-Homepage: http://code.haskell.org/~wren/+Homepage: https://wrengr.org/software/hackage.html+Bug-Reports: https://github.com/wrengr/list-extras/issues Author: wren gayle romano-Maintainer: wren@community.haskell.org-Copyright: Copyright (c) 2007--2015 wren gayle romano+Maintainer: wren@cpan.org+Copyright: Copyright (c) 2007–2021 wren gayle romano License: BSD3 License-File: LICENSE @@ -30,13 +30,23 @@ maintain a separate package I can share the @Data.List.Extras.Foo@ namespace. -Tested-With:- GHC ==6.12.1, GHC ==7.6.1, GHC ==7.8.0 Extra-source-files:- CHANGELOG+ README.md, CHANGELOG++-- This should work as far back as GHC 6.12.1, but we don't verify that by CI.+-- <https://github.com/wrengr/list-extras/actions?query=workflow%3Aci>+Tested-With:+ GHC ==8.0.2,+ GHC ==8.2.2,+ GHC ==8.4.4,+ GHC ==8.6.5,+ GHC ==8.8.4,+ GHC ==8.10.3,+ GHC ==9.0.1+ Source-Repository head- Type: darcs- Location: http://community.haskell.org/~wren/list-extras+ Type: git+ Location: https://github.com/wrengr/list-extras.git ---------------------------------------------------------------- Flag base4@@ -45,6 +55,8 @@ ---------------------------------------------------------------- Library+ Default-Language: Haskell2010+ Hs-Source-Dirs: src Exposed-Modules: Prelude.Listless -- , Data.List.BoehmBerarducci -- , Data.List.Scott
+ src/Data/List/Extras.hs view
@@ -0,0 +1,37 @@+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+-- ~ 2021.10.17+-- |+-- Module : Data.List.Extras+-- Copyright : Copyright (c) 2007--2021 wren gayle romano+-- License : BSD3+-- Maintainer : wren@cpan.org+-- Stability : stable+-- Portability : Haskell98+--+-- This module provides a single header for all @Data.List.Extras.*@+-- modules and provides a small number of other utility functions.+----------------------------------------------------------------++module Data.List.Extras+ (+ list+ , module Data.List.Extras.LazyLength+ , module Data.List.Extras.Pair+ , module Data.List.Extras.Argmax+ ) where++import Data.List.Extras.LazyLength+import Data.List.Extras.Pair+import Data.List.Extras.Argmax++-- | Pattern matching for lists, as a first-class function. (Could+-- also be considered as a non-recursive 'foldr'.) If the list+-- argument is @[]@ then the default argument is returned; otherwise+-- the function is called with the head and tail of the list.+list :: (a -> [a] -> b) -> b -> [a] -> b+list _ z [] = z+list f _ (x:xs) = f x xs++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ src/Data/List/Extras/Argmax.hs view
@@ -0,0 +1,204 @@+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+-- ~ 2021.10.17+-- |+-- Module : Data.List.Extras.Argmax+-- Copyright : Copyright (c) 2007--2021 wren gayle romano+-- License : BSD3+-- Maintainer : wren@cpan.org+-- Stability : experimental+-- Portability : Haskell98+--+-- This module provides variants of the 'maximum' and 'minimum'+-- functions which return the elements for which some function is+-- maximized or minimized.+----------------------------------------------------------------++module Data.List.Extras.Argmax+ (+ -- * Utility functions+ catchNull++ -- * Generic versions+ , argmaxBy, argmaxesBy, argmaxWithMaxBy, argmaxesWithMaxBy++ -- * Maximum variations+ , argmax, argmaxes, argmaxWithMax, argmaxesWithMax++ -- * Minimum variations+ , argmin, argmins, argminWithMin, argminsWithMin++ {- TODO: CPS and monadic variants; argmax2, argmax3,... -}+ {- TODO: make sure argmax et al are "good consumers" for fusion -}+ ) where+-- argmaxM :: (Monad m, Ord b) => (a -> m b) -> [a] -> m (Maybe a)++import Data.List (foldl')++----------------------------------------------------------------+----------------------------------------------------------------++-- | Apply a list function safely, i.e. when the list is non-empty.+-- All other functions will throw errors on empty lists, so use+-- this to make your own safe variations.+catchNull :: ([a] -> b) -> ([a] -> Maybe b)+{-# INLINE catchNull #-}+-- We use the explicit lambda in order to improve inlining in ghc-7.+catchNull f = \xs ->+ case xs of+ [] -> Nothing+ _:_ -> Just (f xs)+++-- | Minimize the number of string literals+emptyListError :: String -> a+{-# NOINLINE emptyListError #-}+emptyListError fun =+ error $ "Data.List.Extras.Argmax."++fun++": empty list"+++-- | Apply a list function unsafely. For internal use.+throwNull :: String -> (a -> [a] -> b) -> ([a] -> b)+{-# INLINE throwNull #-}+-- We use the explicit lambda in order to improve inlining in ghc-7.+throwNull fun f = \xs ->+ case xs of+ [] -> emptyListError fun+ x:xs' -> f x xs'++----------------------------------------------------------------+----------------------------------------------------------------+-- | Tail-recursive driver+_argmaxWithMaxBy :: (b -> b -> Bool) -> (a -> b) -> a -> [a] -> (a,b)+{-# INLINE _argmaxWithMaxBy #-}+-- We use the explicit lambda in order to improve inlining in ghc-7.+_argmaxWithMaxBy isBetterThan f =+ \x xs -> foldl' cmp (x, f x) xs+ where+ cmp bfb@(_,fb) a =+ let fa = f a in+ if fa `isBetterThan` fb+ then (a,fa)+ else bfb+++-- | Tail-recursive driver+_argmaxesWithMaxBy :: (b -> b -> Ordering) -> (a -> b) -> a -> [a] -> ([a],b)+{-# INLINE _argmaxesWithMaxBy #-}+-- We use the explicit lambda in order to improve inlining in ghc-7.+_argmaxesWithMaxBy isBetterEqualThan f =+ \x xs -> foldl' cmp ([x], f x) xs+ where+ cmp bsfb@(bs,fb) a =+ let fa = f a in+ case isBetterEqualThan fa fb of+ GT -> ([a], fa)+ EQ -> (a:bs, fb)+ _ -> bsfb+++_argmaxBy :: (b -> b -> Bool) -> (a -> b) -> a -> [a] -> a+{-# INLINE _argmaxBy #-}+-- We use the point-free style in order to improve inlining in ghc-7.+_argmaxBy k f = (fst .) . _argmaxWithMaxBy k f+++_argmaxesBy :: (b -> b -> Ordering) -> (a -> b) -> a -> [a] -> [a]+{-# INLINE _argmaxesBy #-}+-- We use the point-free style in order to improve inlining in ghc-7.+_argmaxesBy k f = (fst .) . _argmaxesWithMaxBy k f++----------------------------------------------------------------+----------------------------------------------------------------++bool :: (a -> a -> Ordering) -> (a -> a -> Bool)+bool ord = \a b -> ord a b == GT+++-- | Return an element of the list which maximizes the function+-- according to a user-defined ordering.+argmaxBy :: (b -> b -> Ordering) -> (a -> b) -> [a] -> a+argmaxBy ord f = throwNull "argmaxBy"+ $ _argmaxBy (bool ord) f+++-- | Return all elements of the list which maximize the function+-- according to a user-defined ordering.+argmaxesBy :: (b -> b -> Ordering) -> (a -> b) -> [a] -> [a]+argmaxesBy ord f = throwNull "argmaxesBy"+ $ _argmaxesBy ord f+++-- | Return an element of the list which maximizes the function+-- according to a user-defined ordering, and return the value of+-- the function at that element as well.+argmaxWithMaxBy :: (b -> b -> Ordering) -> (a -> b) -> [a] -> (a, b)+argmaxWithMaxBy ord f = throwNull "argmaxWithMaxBy"+ $ _argmaxWithMaxBy (bool ord) f+++-- | Return all elements of the list which maximize the function+-- according to a user-defined ordering, and return the value of+-- the function at those elements as well.+argmaxesWithMaxBy :: (b -> b -> Ordering) -> (a -> b) -> [a] -> ([a], b)+argmaxesWithMaxBy ord f = throwNull "argmaxesWithMaxBy"+ $ _argmaxesWithMaxBy ord f++----------------------------------------------------------------+-- SPECIALIZE on b \in {Int,Integer,Float,Double} for the four+-- functions below nearly doubles the library size (about +21kB).+-- For a basic utility library that's a bit excessive, though if+-- we break the argmax stuff out from list-extras then we might go+-- through with it for performance sake.++-- | Return an element of the list which maximizes the function.+argmax :: (Ord b) => (a -> b) -> [a] -> a+argmax f = throwNull "argmax"+ $ _argmaxBy (>) f++-- | Return all elements of the list which maximize the function.+argmaxes :: (Ord b) => (a -> b) -> [a] -> [a]+argmaxes f = throwNull "argmaxes"+ $ _argmaxesBy compare f+++-- | Return an element of the list which maximizes the function,+-- and return the value of the function at that element as well.+argmaxWithMax :: (Ord b) => (a -> b) -> [a] -> (a, b)+argmaxWithMax f = throwNull "argmaxWithMax"+ $ _argmaxWithMaxBy (>) f+++-- | Return all elements of the list which maximize the function,+-- and return the value of the function at those elements as well.+argmaxesWithMax :: (Ord b) => (a -> b) -> [a] -> ([a], b)+argmaxesWithMax f = throwNull "argmaxesWithMax"+ $ _argmaxesWithMaxBy compare f++----------------------------------------------------------------++-- | Return an element of the list which minimizes the function.+argmin :: (Ord b) => (a -> b) -> [a] -> a+argmin f = throwNull "argmax"+ $ _argmaxBy (<) f++-- | Return all elements of the list which minimize the function.+argmins :: (Ord b) => (a -> b) -> [a] -> [a]+argmins f = throwNull "argmins"+ $ _argmaxesBy (flip compare) f+++-- | Return an element of the list which minimizes the function,+-- and return the value of the function at that element as well.+argminWithMin :: (Ord b) => (a -> b) -> [a] -> (a, b)+argminWithMin f = throwNull "argminWithMin"+ $ _argmaxWithMaxBy (<) f++-- | Return all elements of the list which minimize the function,+-- and return the value of the function at those elements as well.+argminsWithMin :: (Ord b) => (a -> b) -> [a] -> ([a], b)+argminsWithMin f = throwNull "argminsWithMin"+ $ _argmaxesWithMaxBy (flip compare) f++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ src/Data/List/Extras/LazyLength.hs view
@@ -0,0 +1,145 @@++-- 2008.10.12: GHC 6.10 breaks -fno-warn-orphans so that it no+-- longer suppresses the warnings for orphaned RULES. Hence -Werror+-- will make things crash on those systems, and even if that's+-- removed then -Wall will send up too many false positives which+-- may disconcert users.+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}++-- Unfortunately GHC < 6.10 needs -fglasgow-exts in order to actually+-- parse RULES (see -ddump-rules); the -frewrite-rules flag only+-- enables the application of rules, instead of doing what we want.+-- Apparently this is fixed in 6.10.+--+-- http://hackage.haskell.org/trac/ghc/ticket/2213+-- http://www.mail-archive.com/glasgow-haskell-users@haskell.org/msg14313.html+-- OPTIONS_GHC -O2 -fglasgow-exts -frewrite-rules++----------------------------------------------------------------+-- ~ 2021.10.17+-- |+-- Module : Data.List.Extras.LazyLength+-- Copyright : Copyright (c) 2007--2021 wren gayle romano+-- License : BSD3+-- Maintainer : wren@cpan.org+-- Stability : stable+-- Portability : Haskell98+--+-- This module provides least-strict functions for getting a list's+-- length and doing natural things with it.+--+-- The regular version of @length@ will traverse the entire spine+-- of the list in order to return an answer. For comparing the+-- length against some bound, that is by far too strict. Being too+-- strict can cause a space leak by expanding a lazy list before+-- necessary (or more than is ever necessary). And it can lead to+-- unnecessarily non-terminating programs when trying to determine+-- if an infinite list is longer or shorter than some finite bound.+--+-- A nicer version of @length@ would return some lazy approximation+-- of an answer which retains the proper semantics. An option for+-- doing this is to return Peano integers which can be decremented+-- as much as necessary and no further (i.e. at most one more than+-- the bound). Of course, Peano integers are woefully inefficient.+-- This module provides functions with the same lazy effect but+-- does so efficiently instead.+--+-- As of version 0.3.0 the GHC rules to automatically rewrite+-- certain calls to 'length' into our least-strict versions have+-- been /removed/ for more consistent and predictable semantics.+-- All clients should explicitly call these least-strict functions+-- if they want the least-strict behavior.+----------------------------------------------------------------++module Data.List.Extras.LazyLength+ ( lengthBound, lengthCompare+ ) where+++----------------------------------------------------------------+----------------------------------------------------------------+-- | A variant of 'length' which is least-strict for comparing+-- against a boundary length.+--+-- @lengthBound@ is polymorphic in the return of the helper+-- function so we can use 'compare' as well as '>', '>=', '==',+-- '/=', '<=', '<'. If you want to use any other functions, know+-- that we only preserve the ordering of the list's length vs the+-- boundary length and so the function should not rely on the true+-- values of either of the numbers being compared.++lengthBound :: Int -> (Int -> Int -> a) -> [b] -> a+lengthBound n cmp xs+ | n < 0 = case xs of+ [] -> cmp n 0+ (_:_) -> cmp n 1+ | otherwise = go n xs+ where+ go n' [] = cmp n' 0+ go 0 (_:_) = cmp 0 1+ go n' (_:xs') = (go $! n'-1) xs'++{- bad RULES+-- The rules themselves are correct but they alter program semantics+-- regarding bottoms, depending on whether they fire or not.++"lengthBound/(>)" forall n xs. n > length xs = lengthBound n (>) xs+"lengthBound/(>=)" forall n xs. n >= length xs = lengthBound n (>=) xs+"lengthBound/(==)" forall n xs. n == length xs = lengthBound n (==) xs+"lengthBound/(/=)" forall n xs. n /= length xs = lengthBound n (/=) xs+"lengthBound/(<=)" forall n xs. n <= length xs = lengthBound n (<=) xs+"lengthBound/(<)" forall n xs. n < length xs = lengthBound n (<) xs+"lengthBound/compare" forall n xs.+ compare n (length xs) = lengthBound n compare xs++"lengthBound\\(>)" forall n xs. length xs > n = lengthBound n (<) xs+"lengthBound\\(>=)" forall n xs. length xs >= n = lengthBound n (<=) xs+"lengthBound\\(==)" forall n xs. length xs == n = lengthBound n (==) xs+"lengthBound\\(/=)" forall n xs. length xs /= n = lengthBound n (/=) xs+"lengthBound\\(<=)" forall n xs. length xs <= n = lengthBound n (>=) xs+"lengthBound\\(<)" forall n xs. length xs < n = lengthBound n (>) xs+"lengthBound\\compare" forall n xs.+ compare (length xs) n = lengthBound n (flip compare) xs+ -}+++----------------------------------------------------------------+----------------------------------------------------------------+-- | A variant of 'length' which is least-strict for comparing+-- the lengths of two lists. This is as strict as the length of the+-- shorter list (which allows comparing an infinite list against a+-- finite list).+--+-- If you're going to immediately follow this with a 'zip' function+-- then see "Data.List.Extras.Pair" instead.++lengthCompare :: [a] -> [b] -> Ordering+lengthCompare [] [] = EQ+lengthCompare (_:_) [] = GT+lengthCompare [] (_:_) = LT+lengthCompare (_:xs) (_:ys) = lengthCompare xs ys+++{- bad RULES+-- The rules themselves are correct but they alter program semantics+-- regarding bottoms, depending on whether they fire or not.++"lengthCompare/(>)" forall xs ys.+ length xs > length ys = lengthCompare xs ys == GT+"lengthCompare/(>=)" forall xs ys.+ length xs >= length ys = lengthCompare xs ys /= LT+"lengthCompare/(==)" forall xs ys.+ length xs == length ys = lengthCompare xs ys == EQ+"lengthCompare/(/=)" forall xs ys.+ length xs /= length ys = lengthCompare xs ys /= EQ+"lengthCompare/(<=)" forall xs ys.+ length xs <= length ys = lengthCompare xs ys /= GT+"lengthCompare/(<)" forall xs ys.+ length xs < length ys = lengthCompare xs ys == LT++"lengthCompare/compare" forall xs ys.+ compare (length xs) (length ys) = lengthCompare xs ys+ -}++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ src/Data/List/Extras/Pair.hs view
@@ -0,0 +1,136 @@+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+-- ~ 2021.10.17+-- |+-- Module : Data.List.Extras.Pair+-- Copyright : Copyright (c) 2007--2021 wren gayle romano+-- License : BSD3+-- Maintainer : wren@cpan.org+-- Stability : stable+-- Portability : Haskell98+--+-- This module provides safe zipping functions which will fail+-- (return 'Nothing') on uneven length lists.+----------------------------------------------------------------++module Data.List.Extras.Pair+ (+ -- * Safe functions for zipping lists+ pairWithBy, pairWith, pairBy, pair++ -- * Special safe zipping functions+ , biject, biject'++ -- * New (unsafe) zipping functions+ , zipWithBy, zipBy+ ) where+++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: benchmark fusion performance of:+--+-- foldr cons nil .: zipWith (,)+-- zipWithBy (,) cons nil+--+-- ...That is, the latter is a manual fusion of the former, but+-- does zip/zipWith have a special ability to fuse with the incoming+-- lists? Or can foldr fuse with consumers in ways zipWithBy can't?++-- | An unsafe variant of 'pairWithBy' to fill out the interface.+zipWithBy :: (a -> b -> c) -- tuple homomorphism+ -> (c -> d -> d) -> d -- list homomorphism+ -> [a] -> [b] -> d -- a @zip@ function+{-# INLINE zipWithBy #-}+-- We use the explicit lambda in order to improve inlining in ghc-7.+zipWithBy k f z = \xs ys -> zipWB xs ys id+ where+ zipWB (x:xs) (y:ys) cc = zipWB xs ys (cc . f (k x y))+ zipWB _ _ cc = cc z+++-- | A version of 'zip' that uses a user-defined list homomorphism.+zipBy :: ((a,b) -> d -> d) -> d -> [a] -> [b] -> d+{-# INLINE zipBy #-}+zipBy = zipWithBy (,)+++----------------------------------------------------------------+----------------------------------------------------------------+-- | A generic version of 'pair'. The first argument is a tuple+-- homomorphism (i.e. a function for how to combine values from the+-- two lists), the second two arguments form a list homomorphism+-- (i.e. so you can 'foldr' the @[c]@ list directly without actually+-- constructing it).+--+-- In order to evaluate to WHNF 'pairWithBy' is strict in both list+-- arguments, as it must be, to determine that the lists are of the+-- same length. This means it can survive one infinite list (yielding+-- 'Nothing') but that it can't survive two. The implementation is+-- very efficient and uses a tight tail-recursive loop, however+-- with extremely long lists it will be churning through heap and+-- that tightness can make it hard to interrupt (lists of 1 million+-- elements return in 1~2 seconds, but lists of 10 million can lock+-- your system up).++pairWithBy :: (a -> b -> c) -- @(,)@ tuple homomorphism+ -> (c -> d -> d) -- @(:)@ list homomorphism, pt. 1+ -> d -- @[]@ list homomorphism, pt. 2+ -> [a] -> [b] -> Maybe d -- a safer @zip@ function+{-# INLINE pairWithBy #-}+-- We use the explicit lambda in order to improve inlining in ghc-7.+pairWithBy k f z = \xs ys -> pairWB xs ys id+ where+ -- N.B. Strict accumulators are usually awesome, but don't+ -- even consider it when doing CPS! Making @cc@ strict degrades+ -- performance significantly; it takes twice as long and twice+ -- as much heap just to get to WHNF. After evaluating the spine+ -- of the resulting list from 'pair' that drops to +10% time+ -- and +25% heap, which is still much worse.++ pairWB (x:xs) (y:ys) cc = pairWB xs ys (cc . f (k x y))+ pairWB [] [] cc = Just (cc z)+ pairWB _ _ _ = Nothing++-- TODO: we could make this more general still by fusing @f@ and @k@, which we'd often want to do anyways if we're using this full form.++----------------------------------------------------------------++-- | A safe version of 'zipWith'.+pairWith :: (a -> b -> c) -> [a] -> [b] -> Maybe [c]+{-# INLINE pairWith #-}+pairWith f = pairWithBy f (:) []+++-- | A safe version of 'zip' that uses a user-defined list homomorphism.+pairBy :: ((a,b) -> d -> d) -> d -> [a] -> [b] -> Maybe d+{-# INLINE pairBy #-}+pairBy = pairWithBy (,)+++-- | A safe version of 'zip'.+pair :: [a] -> [b] -> Maybe [(a,b)]+{-# INLINE pair #-}+pair = pairWithBy (,) (:) []+++----------------------------------------------------------------+-- These two are just here because they're often requested, and+-- besides they're kinda cute.++-- | A bijection from a list of functions and a list of arguments+-- to a list of results of applying the functions bijectively.+biject :: [a -> b] -> [a] -> Maybe [b]+{-# INLINE biject #-}+biject = pairWith ($) -- 'id' also works+++-- | A version of 'biject' that applies functions strictly. N.B.+-- the list is still lazily evaluated, this just makes the functions+-- strict in their argument.+biject' :: [a -> b] -> [a] -> Maybe [b]+{-# INLINE biject' #-}+biject' = pairWith ($!)++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ src/Prelude/Listless.hs view
@@ -0,0 +1,58 @@+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+{-# LANGUAGE CPP #-}+----------------------------------------------------------------+-- ~ 2021.10.17+-- |+-- Module : Prelude.Listless+-- Copyright : Copyright (c) 2007--2021 wren gayle romano+-- License : BSD3+-- Maintainer : wren@cpan.org+-- Stability : stable+-- Portability : Haskell98 (+CPP)+--+-- This module provides the "Prelude" but removing all the list+-- functions. This is helpful for modules that overload those+-- function names to work for other types. Note that on GHC 7.6 and+-- above @catch@ is no longer exported from the Prelude, and also+-- not re-exported from here; whereas, on earlier versions of GHC+-- (and non-GHC compilers) we still re-export it.+--+-- Be sure to disable the implicit importing of the prelude when+-- you import this one (by passing @-fno-implicit-prelude@ for GHC,+-- or by explicitly importing the prelude with an empty import list+-- for most implementations).+----------------------------------------------------------------++module Prelude.Listless+ -- We have to manually specify the exports; can't export @module+ -- Prelude@ because that'll export everything and only hide the+ -- noted parts from this module, which is meaningless.+ (($!), ($), (&&), (.), (=<<), Bool(..), Bounded(..), Char,+ Double, Either(..), Enum(..), Eq(..), FilePath, Float, Floating(..),+ Fractional(..), Functor(..), IO, IOError, Int, Integer,+ Integral(..), Maybe(..), Monad(..), Num(..), Ord(..), Ordering(..),+ Rational, Read(..), ReadS, Real(..), RealFloat(..), RealFrac(..),+ Show(..), ShowS, String, (^), (^^), appendFile, asTypeOf,+#if __GLASGOW_HASKELL__ < 706+ catch,+#endif+ const, curry, either, error, even, flip, fromIntegral, fst,+ gcd, getChar, getContents, getLine, id, interact, ioError, lcm,+ lex, maybe, not, odd, otherwise, print, putChar, putStr, putStrLn,+ read, readFile, readIO, readLn, readParen, reads, realToFrac,+ seq, showChar, showParen, showString, shows, snd, subtract,+ uncurry, undefined, until, userError, writeFile, (||))++ where++import Prelude hiding+ ((!!), (++), all, and, any, break, concat, concatMap, cycle,+ drop, dropWhile, elem, filter, foldl, foldl1, foldr, foldr1,+ head, init, iterate, last, length, lines, lookup, map, mapM,+ mapM_, maximum, minimum, notElem, null, or, product, repeat,+ replicate, reverse, scanl, scanl1, scanr, scanr1, sequence,+ sequence_, span, splitAt, sum, tail, take, takeWhile, unlines,+ unwords, unzip, unzip3, words, zip, zip3, zipWith, zipWith3)++----------------------------------------------------------------+----------------------------------------------------------- fin.