packages feed

ListLike (empty) → 1.0.0

raw patch · 12 files changed

+2721/−0 lines, 12 filesdep +basedep +haskell98dep +mtlbuild-type:Customsetup-changed

Dependencies added: base, haskell98, mtl

Files

+ COPYING view
@@ -0,0 +1,510 @@++                  GNU LESSER GENERAL PUBLIC LICENSE+                       Version 2.1, February 1999++ Copyright (C) 1991, 1999 Free Software Foundation, Inc.+	51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++[This is the first released version of the Lesser GPL.  It also counts+ as the successor of the GNU Library Public License, version 2, hence+ the version number 2.1.]++                            Preamble++  The licenses for most software are designed to take away your+freedom to share and change it.  By contrast, the GNU General Public+Licenses are intended to guarantee your freedom to share and change+free software--to make sure the software is free for all its users.++  This license, the Lesser General Public License, applies to some+specially designated software packages--typically libraries--of the+Free Software Foundation and other authors who decide to use it.  You+can use it too, but we suggest you first think carefully about whether+this license or the ordinary General Public License is the better+strategy to use in any particular case, based on the explanations+below.++  When we speak of free software, we are referring to freedom of use,+not price.  Our General Public Licenses are designed to make sure that+you have the freedom to distribute copies of free software (and charge+for this service if you wish); that you receive source code or can get+it if you want it; that you can change the software and use pieces of+it in new free programs; and that you are informed that you can do+these things.++  To protect your rights, we need to make restrictions that forbid+distributors to deny you these rights or to ask you to surrender these+rights.  These restrictions translate to certain responsibilities for+you if you distribute copies of the library or if you modify it.++  For example, if you distribute copies of the library, whether gratis+or for a fee, you must give the recipients all the rights that we gave+you.  You must make sure that they, too, receive or can get the source+code.  If you link other code with the library, you must provide+complete object files to the recipients, so that they can relink them+with the library after making changes to the library and recompiling+it.  And you must show them these terms so they know their rights.++  We protect your rights with a two-step method: (1) we copyright the+library, and (2) we offer you this license, which gives you legal+permission to copy, distribute and/or modify the library.++  To protect each distributor, we want to make it very clear that+there is no warranty for the free library.  Also, if the library is+modified by someone else and passed on, the recipients should know+that what they have is not the original version, so that the original+author's reputation will not be affected by problems that might be+introduced by others.++  Finally, software patents pose a constant threat to the existence of+any free program.  We wish to make sure that a company cannot+effectively restrict the users of a free program by obtaining a+restrictive license from a patent holder.  Therefore, we insist that+any patent license obtained for a version of the library must be+consistent with the full freedom of use specified in this license.++  Most GNU software, including some libraries, is covered by the+ordinary GNU General Public License.  This license, the GNU Lesser+General Public License, applies to certain designated libraries, and+is quite different from the ordinary General Public License.  We use+this license for certain libraries in order to permit linking those+libraries into non-free programs.++  When a program is linked with a library, whether statically or using+a shared library, the combination of the two is legally speaking a+combined work, a derivative of the original library.  The ordinary+General Public License therefore permits such linking only if the+entire combination fits its criteria of freedom.  The Lesser General+Public License permits more lax criteria for linking other code with+the library.++  We call this license the "Lesser" General Public License because it+does Less to protect the user's freedom than the ordinary General+Public License.  It also provides other free software developers Less+of an advantage over competing non-free programs.  These disadvantages+are the reason we use the ordinary General Public License for many+libraries.  However, the Lesser license provides advantages in certain+special circumstances.++  For example, on rare occasions, there may be a special need to+encourage the widest possible use of a certain library, so that it+becomes a de-facto standard.  To achieve this, non-free programs must+be allowed to use the library.  A more frequent case is that a free+library does the same job as widely used non-free libraries.  In this+case, there is little to gain by limiting the free library to free+software only, so we use the Lesser General Public License.++  In other cases, permission to use a particular library in non-free+programs enables a greater number of people to use a large body of+free software.  For example, permission to use the GNU C Library in+non-free programs enables many more people to use the whole GNU+operating system, as well as its variant, the GNU/Linux operating+system.++  Although the Lesser General Public License is Less protective of the+users' freedom, it does ensure that the user of a program that is+linked with the Library has the freedom and the wherewithal to run+that program using a modified version of the Library.++  The precise terms and conditions for copying, distribution and+modification follow.  Pay close attention to the difference between a+"work based on the library" and a "work that uses the library".  The+former contains code derived from the library, whereas the latter must+be combined with the library in order to run.++                  GNU LESSER GENERAL PUBLIC LICENSE+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++  0. This License Agreement applies to any software library or other+program which contains a notice placed by the copyright holder or+other authorized party saying it may be distributed under the terms of+this Lesser General Public License (also called "this License").+Each licensee is addressed as "you".++  A "library" means a collection of software functions and/or data+prepared so as to be conveniently linked with application programs+(which use some of those functions and data) to form executables.++  The "Library", below, refers to any such software library or work+which has been distributed under these terms.  A "work based on the+Library" means either the Library or any derivative work under+copyright law: that is to say, a work containing the Library or a+portion of it, either verbatim or with modifications and/or translated+straightforwardly into another language.  (Hereinafter, translation is+included without limitation in the term "modification".)++  "Source code" for a work means the preferred form of the work for+making modifications to it.  For a library, complete source code means+all the source code for all modules it contains, plus any associated+interface definition files, plus the scripts used to control+compilation and installation of the library.++  Activities other than copying, distribution and modification are not+covered by this License; they are outside its scope.  The act of+running a program using the Library is not restricted, and output from+such a program is covered only if its contents constitute a work based+on the Library (independent of the use of the Library in a tool for+writing it).  Whether that is true depends on what the Library does+and what the program that uses the Library does.++  1. You may copy and distribute verbatim copies of the Library's+complete source code as you receive it, in any medium, provided that+you conspicuously and appropriately publish on each copy an+appropriate copyright notice and disclaimer of warranty; keep intact+all the notices that refer to this License and to the absence of any+warranty; and distribute a copy of this License along with the+Library.++  You may charge a fee for the physical act of transferring a copy,+and you may at your option offer warranty protection in exchange for a+fee.++  2. You may modify your copy or copies of the Library or any portion+of it, thus forming a work based on the Library, and copy and+distribute such modifications or work under the terms of Section 1+above, provided that you also meet all of these conditions:++    a) The modified work must itself be a software library.++    b) You must cause the files modified to carry prominent notices+    stating that you changed the files and the date of any change.++    c) You must cause the whole of the work to be licensed at no+    charge to all third parties under the terms of this License.++    d) If a facility in the modified Library refers to a function or a+    table of data to be supplied by an application program that uses+    the facility, other than as an argument passed when the facility+    is invoked, then you must make a good faith effort to ensure that,+    in the event an application does not supply such function or+    table, the facility still operates, and performs whatever part of+    its purpose remains meaningful.++    (For example, a function in a library to compute square roots has+    a purpose that is entirely well-defined independent of the+    application.  Therefore, Subsection 2d requires that any+    application-supplied function or table used by this function must+    be optional: if the application does not supply it, the square+    root function must still compute square roots.)++These requirements apply to the modified work as a whole.  If+identifiable sections of that work are not derived from the Library,+and can be reasonably considered independent and separate works in+themselves, then this License, and its terms, do not apply to those+sections when you distribute them as separate works.  But when you+distribute the same sections as part of a whole which is a work based+on the Library, the distribution of the whole must be on the terms of+this License, whose permissions for other licensees extend to the+entire whole, and thus to each and every part regardless of who wrote+it.++Thus, it is not the intent of this section to claim rights or contest+your rights to work written entirely by you; rather, the intent is to+exercise the right to control the distribution of derivative or+collective works based on the Library.++In addition, mere aggregation of another work not based on the Library+with the Library (or with a work based on the Library) on a volume of+a storage or distribution medium does not bring the other work under+the scope of this License.++  3. You may opt to apply the terms of the ordinary GNU General Public+License instead of this License to a given copy of the Library.  To do+this, you must alter all the notices that refer to this License, so+that they refer to the ordinary GNU General Public License, version 2,+instead of to this License.  (If a newer version than version 2 of the+ordinary GNU General Public License has appeared, then you can specify+that version instead if you wish.)  Do not make any other change in+these notices.++  Once this change is made in a given copy, it is irreversible for+that copy, so the ordinary GNU General Public License applies to all+subsequent copies and derivative works made from that copy.++  This option is useful when you wish to copy part of the code of+the Library into a program that is not a library.++  4. You may copy and distribute the Library (or a portion or+derivative of it, under Section 2) in object code or executable form+under the terms of Sections 1 and 2 above provided that you accompany+it with the complete corresponding machine-readable source code, which+must be distributed under the terms of Sections 1 and 2 above on a+medium customarily used for software interchange.++  If distribution of object code is made by offering access to copy+from a designated place, then offering equivalent access to copy the+source code from the same place satisfies the requirement to+distribute the source code, even though third parties are not+compelled to copy the source along with the object code.++  5. A program that contains no derivative of any portion of the+Library, but is designed to work with the Library by being compiled or+linked with it, is called a "work that uses the Library".  Such a+work, in isolation, is not a derivative work of the Library, and+therefore falls outside the scope of this License.++  However, linking a "work that uses the Library" with the Library+creates an executable that is a derivative of the Library (because it+contains portions of the Library), rather than a "work that uses the+library".  The executable is therefore covered by this License.+Section 6 states terms for distribution of such executables.++  When a "work that uses the Library" uses material from a header file+that is part of the Library, the object code for the work may be a+derivative work of the Library even though the source code is not.+Whether this is true is especially significant if the work can be+linked without the Library, or if the work is itself a library.  The+threshold for this to be true is not precisely defined by law.++  If such an object file uses only numerical parameters, data+structure layouts and accessors, and small macros and small inline+functions (ten lines or less in length), then the use of the object+file is unrestricted, regardless of whether it is legally a derivative+work.  (Executables containing this object code plus portions of the+Library will still fall under Section 6.)++  Otherwise, if the work is a derivative of the Library, you may+distribute the object code for the work under the terms of Section 6.+Any executables containing that work also fall under Section 6,+whether or not they are linked directly with the Library itself.++  6. As an exception to the Sections above, you may also combine or+link a "work that uses the Library" with the Library to produce a+work containing portions of the Library, and distribute that work+under terms of your choice, provided that the terms permit+modification of the work for the customer's own use and reverse+engineering for debugging such modifications.++  You must give prominent notice with each copy of the work that the+Library is used in it and that the Library and its use are covered by+this License.  You must supply a copy of this License.  If the work+during execution displays copyright notices, you must include the+copyright notice for the Library among them, as well as a reference+directing the user to the copy of this License.  Also, you must do one+of these things:++    a) Accompany the work with the complete corresponding+    machine-readable source code for the Library including whatever+    changes were used in the work (which must be distributed under+    Sections 1 and 2 above); and, if the work is an executable linked+    with the Library, with the complete machine-readable "work that+    uses the Library", as object code and/or source code, so that the+    user can modify the Library and then relink to produce a modified+    executable containing the modified Library.  (It is understood+    that the user who changes the contents of definitions files in the+    Library will not necessarily be able to recompile the application+    to use the modified definitions.)++    b) Use a suitable shared library mechanism for linking with the+    Library.  A suitable mechanism is one that (1) uses at run time a+    copy of the library already present on the user's computer system,+    rather than copying library functions into the executable, and (2)+    will operate properly with a modified version of the library, if+    the user installs one, as long as the modified version is+    interface-compatible with the version that the work was made with.++    c) Accompany the work with a written offer, valid for at least+    three years, to give the same user the materials specified in+    Subsection 6a, above, for a charge no more than the cost of+    performing this distribution.++    d) If distribution of the work is made by offering access to copy+    from a designated place, offer equivalent access to copy the above+    specified materials from the same place.++    e) Verify that the user has already received a copy of these+    materials or that you have already sent this user a copy.++  For an executable, the required form of the "work that uses the+Library" must include any data and utility programs needed for+reproducing the executable from it.  However, as a special exception,+the materials to be distributed need not include anything that is+normally distributed (in either source or binary form) with the major+components (compiler, kernel, and so on) of the operating system on+which the executable runs, unless that component itself accompanies+the executable.++  It may happen that this requirement contradicts the license+restrictions of other proprietary libraries that do not normally+accompany the operating system.  Such a contradiction means you cannot+use both them and the Library together in an executable that you+distribute.++  7. You may place library facilities that are a work based on the+Library side-by-side in a single library together with other library+facilities not covered by this License, and distribute such a combined+library, provided that the separate distribution of the work based on+the Library and of the other library facilities is otherwise+permitted, and provided that you do these two things:++    a) Accompany the combined library with a copy of the same work+    based on the Library, uncombined with any other library+    facilities.  This must be distributed under the terms of the+    Sections above.++    b) Give prominent notice with the combined library of the fact+    that part of it is a work based on the Library, and explaining+    where to find the accompanying uncombined form of the same work.++  8. You may not copy, modify, sublicense, link with, or distribute+the Library except as expressly provided under this License.  Any+attempt otherwise to copy, modify, sublicense, link with, or+distribute the Library is void, and will automatically terminate your+rights under this License.  However, parties who have received copies,+or rights, from you under this License will not have their licenses+terminated so long as such parties remain in full compliance.++  9. You are not required to accept this License, since you have not+signed it.  However, nothing else grants you permission to modify or+distribute the Library or its derivative works.  These actions are+prohibited by law if you do not accept this License.  Therefore, by+modifying or distributing the Library (or any work based on the+Library), you indicate your acceptance of this License to do so, and+all its terms and conditions for copying, distributing or modifying+the Library or works based on it.++  10. Each time you redistribute the Library (or any work based on the+Library), the recipient automatically receives a license from the+original licensor to copy, distribute, link with or modify the Library+subject to these terms and conditions.  You may not impose any further+restrictions on the recipients' exercise of the rights granted herein.+You are not responsible for enforcing compliance by third parties with+this License.++  11. If, as a consequence of a court judgment or allegation of patent+infringement or for any other reason (not limited to patent issues),+conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License.  If you cannot+distribute so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you+may not distribute the Library at all.  For example, if a patent+license would not permit royalty-free redistribution of the Library by+all those who receive copies directly or indirectly through you, then+the only way you could satisfy both it and this License would be to+refrain entirely from distribution of the Library.++If any portion of this section is held invalid or unenforceable under+any particular circumstance, the balance of the section is intended to+apply, and the section as a whole is intended to apply in other+circumstances.++It is not the purpose of this section to induce you to infringe any+patents or other property right claims or to contest validity of any+such claims; this section has the sole purpose of protecting the+integrity of the free software distribution system which is+implemented by public license practices.  Many people have made+generous contributions to the wide range of software distributed+through that system in reliance on consistent application of that+system; it is up to the author/donor to decide if he or she is willing+to distribute software through any other system and a licensee cannot+impose that choice.++This section is intended to make thoroughly clear what is believed to+be a consequence of the rest of this License.++  12. If the distribution and/or use of the Library is restricted in+certain countries either by patents or by copyrighted interfaces, the+original copyright holder who places the Library under this License+may add an explicit geographical distribution limitation excluding those+countries, so that distribution is permitted only in or among+countries not thus excluded.  In such case, this License incorporates+the limitation as if written in the body of this License.++  13. The Free Software Foundation may publish revised and/or new+versions of the Lesser General Public License from time to time.+Such new versions will be similar in spirit to the present version,+but may differ in detail to address new problems or concerns.++Each version is given a distinguishing version number.  If the Library+specifies a version number of this License which applies to it and+"any later version", you have the option of following the terms and+conditions either of that version or of any later version published by+the Free Software Foundation.  If the Library does not specify a+license version number, you may choose any version ever published by+the Free Software Foundation.++  14. If you wish to incorporate parts of the Library into other free+programs whose distribution conditions are incompatible with these,+write to the author to ask for permission.  For software which is+copyrighted by the Free Software Foundation, write to the Free+Software Foundation; we sometimes make exceptions for this.  Our+decision will be guided by the two goals of preserving the free status+of all derivatives of our free software and of promoting the sharing+and reuse of software generally.++                            NO WARRANTY++  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.++  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH+DAMAGES.++                     END OF TERMS AND CONDITIONS++           How to Apply These Terms to Your New Libraries++  If you develop a new library, and you want it to be of the greatest+possible use to the public, we recommend making it free software that+everyone can redistribute and change.  You can do so by permitting+redistribution under these terms (or, alternatively, under the terms+of the ordinary General Public License).++  To apply these terms, attach the following notices to the library.+It is safest to attach them to the start of each source file to most+effectively convey the exclusion of warranty; and each file should+have at least the "copyright" line and a pointer to where the full+notice is found.+++    <one line to give the library's name and a brief idea of what it does.>+    Copyright (C) <year>  <name of author>++    This library is free software; you can redistribute it and/or+    modify it under the terms of the GNU Lesser General Public+    License as published by the Free Software Foundation; either+    version 2.1 of the License, or (at your option) any later version.++    This library is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+    Lesser General Public License for more details.++    You should have received a copy of the GNU Lesser General Public+    License along with this library; if not, write to the Free Software+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA++Also add information on how to contact you by electronic and paper mail.++You should also get your employer (if you work as a programmer) or+your school, if any, to sign a "copyright disclaimer" for the library,+if necessary.  Here is a sample; alter the names:++  Yoyodyne, Inc., hereby disclaims all copyright interest in the+  library `Frob' (a library for tweaking knobs) written by James+  Random Hacker.++  <signature of Ty Coon>, 1 April 1990+  Ty Coon, President of Vice++That's all there is to it!++
@@ -0,0 +1,25 @@+listlike+Copyright (C) 2007 John Goerzen <jgoerzen@complete.org>++All code is under the following license unless otherwise noted:+   This program is free software; you can redistribute it and/or modify+   it under the terms of the GNU Lesser General Public License as published by+   the Free Software Foundation; either version 2.1 of the License, or+   (at your option) any later version.++   This program is distributed in the hope that it will be useful,+   but WITHOUT ANY WARRANTY; without even the implied warranty of+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+   GNU Lesser General Public License for more details.++   You should have received a copy of the GNU General Public License+   along with this program; if not, write to the Free Software+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA++The GNU General Public License is available in the file COPYING in the source+distribution.  Debian GNU/Linux users may find this in+/usr/share/common-licenses/LGPL-2.1.++If the LGPL is unacceptable for your uses, please e-mail me; alternative+terms can be negotiated for your project.+
+ ListLike.cabal view
@@ -0,0 +1,43 @@+Name: ListLike+Version: 1.0.0+License: LGPL+Maintainer: John Goerzen <jgoerzen@complete.org>+Author: John Goerzen+Copyright: Copyright (c) 2007 John Goerzen+license-file: COPYRIGHT+extra-source-files: COPYING+Category: Generics+homepage: http://software.complete.org/listlike+synopsis: Generic support for list-like structures+Description: Generic support for list-like structures in Haskell.+ .+ The ListLike module provides a common interface to the various Haskell+ types that are list-like.  Predefined interfaces include standard+ Haskell lists, Arrays, ByteStrings, and lazy ByteStrings.  Custom+ types can easily be made ListLike instances as well.+ .+ ListLike also provides for String-like types, such as String and+ ByteString, for types that support input and output, and for types that can handle+ infinite lists.+Stability: Stable+Hs-Source-Dirs: src+Exposed-Modules: Data.ListLike,+        Data.ListLike.Base,+        Data.ListLike.FoldableLL,+        Data.ListLike.IO,+        Data.ListLike.Instances,+        Data.ListLike.String,+        Data.ListLike.Utils+-- Other-Modules: Data.ConfigFile.Lexer+Extensions: ExistentialQuantification, OverlappingInstances, +   UndecidableInstances+Build-Depends: base,+               haskell98, mtl+GHC-Options: -O2++Executable: runtests+Buildable: False+Main-Is: runtests.hs+HS-Source-Dirs: testsrc, .+Extensions: ExistentialQuantification, OverlappingInstances,+    UndecidableInstances, CPP
+ Setup.hs view
@@ -0,0 +1,5 @@+#!/usr/bin/env runhaskell+import Distribution.Simple++main = defaultMain+
+ src/Data/ListLike.hs view
@@ -0,0 +1,256 @@+{-+Copyright (C) 2007 John Goerzen <jgoerzen@complete.org>++All rights reserved.++For license and copyright information, see the file COPYRIGHT++-}++{- |+   Module     : Data.ListLike+   Copyright  : Copyright (C) 2007 John Goerzen+   License    : LGPL++   Maintainer : John Goerzen <jgoerzen@complete.org>+   Stability  : provisional+   Portability: portable++Generic operations over list-like structures++Written by John Goerzen, jgoerzen\@complete.org++Please start with the introduction at "Data.ListLike#intro".+-}++module Data.ListLike +                (-- * Introduction+                 -- $intro+                 +                 -- * Creation & Basic Functions+                 empty, singleton, +                 cons, snoc, append, head, last, tail, init, null, length,+                 -- * List transformations+                 map, rigidMap, reverse, intersperse,+                 -- ** Conversions+                 toList, fromList, fromListLike,+                 -- * Reducing lists (folds), from "FoldableLL"+                 foldl, foldl', foldl1, foldr, foldr', foldr1,+                 -- ** Special folds+                 concat, concatMap, rigidConcatMap,+                 and, or,+                 any, all,+                 sum, product,+                 maximum, minimum,+                 fold, foldMap,+                 -- * Building lists+                 -- ** Scans+                 -- ** Accumulating maps+                 -- ** Infinite lists+                 iterate, repeat, replicate, cycle,+                 -- ** Unfolding+                 -- * Sublists+                 -- ** Extracting sublists+                 take, drop, splitAt, takeWhile, dropWhile, span, break,+                 group, inits, tails, +                 -- ** Predicates+                 isPrefixOf, isSuffixOf, isInfixOf,+                 -- * Searching lists+                 -- ** Searching by equality+                 elem, notElem,+                 -- ** Searching with a predicate+                 find, filter, partition,+                 -- * Indexing lists+                 index, elemIndex, elemIndices, findIndex, findIndices,+                 -- * Zipping and unzipping lists+                 zip, zipWith, unzip,+                 -- * Monadic Operations+                 sequence, sequence_, mapM, rigidMapM, mapM_,+                 -- * Input and Output+                 ListLikeIO(..),+                 -- * Special lists+                 -- ** Strings+                 toString, fromString, lines, words,+                 -- ** \"Set\" operations+                 nub, delete, deleteFirsts, union, intersect,+                 -- ** Ordered lists+                 sort, insert,+                 -- * Generalized functions+                 -- ** The \"By\" operations+                 -- *** User-supplied equality (replacing an Eq context)+                 nubBy, deleteBy, deleteFirstsBy, unionBy, intersectBy,+                 groupBy,+                 -- *** User-supplied comparison (replacing an Ord context)+                 sortBy, insertBy, -- maximumBy, minimumBy,+                 -- ** The \"generic\" operations+                 genericLength, genericTake, genericDrop, genericSplitAt,+                 -- genericIndex,+                 genericReplicate,+                 -- * Notes on specific instances+                 -- ** Lists+                 -- $noteslist++                 -- ** Arrays+                 -- $notesarray++                 -- ** Maps+                 -- $notesmap++                 -- ** ByteStrings+                 -- $notesbytestring+                 +                 -- * Base Typeclasses+                 -- ** The ListLike class+                 ListLike,+                 -- ** The FoldableLL class+                 FoldableLL,+                 -- ** The StringLike class+                 StringLike,+                 -- ** The InfiniteListLike class+                 InfiniteListLike+                )+       where+import Prelude hiding (length, head, last, null, tail, map, filter, concat, +                       any, lookup, init, all, foldl, foldr, foldl1, foldr1,+                       maximum, minimum, iterate, span, break, takeWhile,+                       dropWhile, reverse, zip, zipWith, sequence,+                       sequence_, mapM, mapM_, concatMap, and, or, sum,+                       product, repeat, replicate, cycle, take, drop,+                       splitAt, elem, notElem, unzip, lines, words,+                       unlines, unwords)+import Data.ListLike.Base+import Data.ListLike.FoldableLL+import Data.ListLike.Instances()+import Data.ListLike.String+import Data.ListLike.Utils+import Data.ListLike.IO++{- $intro+ #intro#+Welcome to ListLike.++This module provides abstractions over typical list operations.+It is designed to let you freely interchange different ways to represent+sequences of data.  It works with lists, various types of ByteStrings,+and much more.++In this module, you'll find generic versions of most of the functions+you're used to using in the "Prelude", "Data.List", and "System.IO".+They carry the+same names, too.  Therefore, you'll want to be careful how you import+the module.  I suggest using:++>import qualified ListLike as LL++Then, you can use LL.fold, LL.map, etc. to get the generic version of+the functions you want.  Alternatively, you can hide the other versions+from Prelude and import specific generic functions from here, such as:++>import Prelude hiding (map)+>import ListLike (map)++The I\/O features of ListLike may a+The module "Data.ListLike" actually simply re-exports the items found+in a number of its sub-modules.  If you want a smaller subset of+"Data.ListLike", look at the documentation for its sub-modules and import+the relevant one.++In most cases, functions here can act as drop-in replacements for their+list-specific counterparts.  They will use the same underlying implementations+for lists, so there should be no performance difference.+    +You can make your own types instances of 'ListLike' as well.  For more+details, see the notes for the 'ListLike' typeclass.+-}++{- $noteslist++Functions for operating on regular lists almost all use the native+implementations in "Data.List", "Prelude", or similar standard+modules.  The exceptions are:++* 'mapM' uses the default 'ListLike' implementation++* 'hGet' does not exist for 'String' in the Haskell modules.+  It is implemented in terms of "Data.ByteString.Lazy".++* 'hGetNonBlocking' is the same way. -}++{- $notesarray++'Data.Array.Array' is an instance of 'ListLike'.  Here are some notes about it:++* The index you use must be an integral++* 'ListLike' functions that take an index always take a 0-based index+  for compatibility with other 'ListLike' instances.+  This is translated by the instance functions into the proper offset from+  the bounds in the Array.++* 'ListLike' functions preserve the original Array index numbers when+  possible.  Functions such as 'cons' will reduce the lower bound to do+  their job.  'snoc' and 'append' increase the upper bound.  'drop' raises+  the lower bound and 'take' lowers the upper bound.++* Functions that change the length of the array by an amount not known+  in advance, such as 'filter', will generate a new array with the lower+  bound set to 0.  Furthermore, these functions cannot operate on infinite+  lists because they must know their length in order to generate the+  array.  'hGetContents' and its friends will therefore require the+  entire file to be read into memory before processing is possible.++* 'empty', 'singleton', and 'fromList' also generate an array with the+  lower bound set to 0.++* Many of these functions will generate runtime exceptions if you have+  not assigned a value to every slot in the array.+-}++{- $notesmap++'Data.Map.Map' is an instance of 'ListLike' and is a rather interesting one at+that.  The \"item\" for the Map instance is a @(key, value)@ pair.  This+permits you to do folds, maps, etc. over a Map just like you would on a list.++The nature of a Map -- that every key is unique, and that it is internally+sorted -- means that there are some special things to take note of:++* 'cons' may or may not actually increase the size of the Map.  If the given+   key is already in the map, its value will simply be updated.  Since+   a Map has a set internal ordering, it is also not guaranteed that cons+   will add something to the beginning of the Map.++* 'snoc' is the same operation as 'cons'.++* 'append' is 'Data.Map.union'++* 'nub', 'nubBy',+  'reverse', 'sort', 'sortBy', etc. are the identity function and don\'t+  actually perform any computation++* 'insert' is the same as 'cons'.++* 'replicate' and 'genericReplicate' ignore the count and return a Map+  with a single element.+-}++{- $notesbytestring++Both strict and lazy ByteStreams can be used with 'ListLike'.++Most 'ListLike' operations map directly to ByteStream options.  Notable+exceptions:++* 'map' uses the 'ListLike' implementation.  'rigidMap' is more efficient.+  The same goes for 'concatMap' vs. 'rigidConcatMap'.++* 'isInfixOf', 'sequence', 'mapM' and similar monad operations, 'insert', +  'union', 'intersect', 'sortBy', and similar functions are not implemented+  in 'ByteStream' and use a naive default implementation.++* The lazy ByteStream module implements fewer funtions than the strict+  ByteStream module.  In some cases, default implementations are used.+  In others, notably related to I\/O, the lazy ByteStreams are converted+  back and forth to strict ones as appropriate.++-}
+ src/Data/ListLike/Base.hs view
@@ -0,0 +1,630 @@+{-+Copyright (C) 2007 John Goerzen <jgoerzen@complete.org>++All rights reserved.++For license and copyright information, see the file COPYRIGHT++-}++{- |+   Module     : Data.ListLike.Base+   Copyright  : Copyright (C) 2007 John Goerzen+   License    : LGPL++   Maintainer : John Goerzen <jgoerzen@complete.org>+   Stability  : provisional+   Portability: portable++Generic operations over list-like structures++Written by John Goerzen, jgoerzen\@complete.org+-}++module Data.ListLike.Base +    (+    ListLike(..),+    InfiniteListLike(..),+    zip, zipWith, sequence_+    ) where+import Prelude hiding (length, head, last, null, tail, map, filter, concat, +                       any, lookup, init, all, foldl, foldr, foldl1, foldr1,+                       maximum, minimum, iterate, span, break, takeWhile,+                       dropWhile, reverse, zip, zipWith, sequence,+                       sequence_, mapM, mapM_, concatMap, and, or, sum,+                       product, repeat, replicate, cycle, take, drop,+                       splitAt, elem, notElem, unzip, lines, words,+                       unlines, unwords)+import qualified Data.List as L+import Data.ListLike.FoldableLL+import qualified Control.Monad as M+import Data.Monoid+import Data.Maybe++{- | The class implementing list-like functions.++It is worth noting that types such as 'Data.Map.Map' can be instances of+'ListLike'.  Due to their specific ways of operating, they may not behave+in the expected way in some cases.  For instance, 'cons' may not increase+the size of a map if the key you have given is already in the map; it will+just replace the value already there.++Implementators must define at least:++* singleton++* head++* tail++* null or genericLength+-}+class (FoldableLL full item, Monoid full) =>+    ListLike full item | full -> item where++    ------------------------------ Creation+    {- | The empty list -}+    empty :: full+    empty = mempty++    {- | Creates a single-itement list out of an itement -}+    singleton :: item -> full++    ------------------------------ Basic Functions++    {- | Like (:) for lists: adds an itement to the beginning of a list -}+    cons :: item -> full -> full+    cons item l = append (singleton item) l++    {- | Adds an itement to the *end* of a 'ListLike'. -}+    snoc :: full -> item -> full+    snoc l item = append l (singleton item)++    {- | Combines two lists.  Like (++). -}+    append :: full -> full -> full +    append = mappend++    {- | Extracts the first itement of a 'ListLike'. -}+    head :: full -> item++    {- | Extracts the last itement of a 'ListLike'. -}+    last :: full -> item+    last l = case genericLength l of+                  (0::Integer) -> error "Called last on empty list"+                  1 -> head l+                  _ -> last (tail l)++    {- | Gives all itements after the head. -}+    tail :: full -> full ++    {- | All elements of the list except the last one.  See also 'inits'. -}+    init :: full -> full+    init l+        | null l = error "init: empty list"+        | null xs = empty+        | otherwise = cons (head l) (init xs)+        where xs = tail l++    {- | Tests whether the list is empty. -}+    null :: full -> Bool+    null x = genericLength x == (0::Integer)++    {- | Length of the list.  See also 'genericLength'. -}+    length :: full -> Int+    length = genericLength++    ------------------------------ List Transformations++    {- | Apply a function to each element, returning any other+         valid 'ListLike'.  'rigidMap' will always be at least+         as fast, if not faster, than this function and is recommended+         if it will work for your purposes.  See also 'mapM'. -}+    map :: ListLike full' item' => (item -> item') -> full -> full'+    map func inp  +        | null inp = empty+        | otherwise = cons (func (head inp)) (map func (tail inp))++    {- | Like 'map', but without the possibility of changing the type of+       the item.  This can have performance benefits for things such as+       ByteStrings, since it will let the ByteString use its native+       low-level map implementation. -}+    rigidMap :: (item -> item) -> full -> full+    rigidMap = map++    {- | Reverse the elements in a list. -}+    reverse :: full -> full +    reverse l = rev l empty+        where rev rl a+                | null rl = a+                | otherwise = rev (tail rl) (cons (head rl) a)+    {- | Add an item between each element in the structure -}+    intersperse :: item -> full -> full+    intersperse sep l+        | null l = empty+        | null xs = singleton x+        | otherwise = cons x (cons sep (intersperse sep xs))+        where x = head l+              xs = tail l++    ------------------------------ Reducing Lists (folds)+    -- See also functions in FoldableLLL++    ------------------------------ Special folds+    {- | Flatten the structure. -}+    concat :: (ListLike full' full, Monoid full) => full' -> full+    concat = fold++    {- | Map a function over the items and concatenate the results.+         See also 'rigidConcatMap'.-}+    concatMap :: (ListLike full' item') =>+                 (item -> full') -> full -> full'+    concatMap = foldMap++    {- | Like 'concatMap', but without the possibility of changing+         the type of the item.  This can have performance benefits+         for some things such as ByteString. -}+    rigidConcatMap :: (item -> full) -> full -> full+    rigidConcatMap = concatMap++    {- | True if any items satisfy the function -}+    any :: (item -> Bool) -> full -> Bool+    any p = getAny . foldMap (Any . p)++    {- | True if all items satisfy the function -}+    all :: (item -> Bool) -> full -> Bool+    all p = getAll . foldMap (All . p)++    {- | The maximum value of the list -}+    maximum :: Ord item => full -> item+    maximum = foldr1 max++    {- | The minimum value of the list -}+    minimum :: Ord item => full -> item+    minimum = foldr1 min++    ------------------------------ Infinite lists+    {- | Generate a structure with the specified length with every element+    set to the item passed in.  See also 'genericReplicate' -}+    replicate :: Int -> item -> full+    replicate = genericReplicate++    ------------------------------ Sublists+    {- | Takes the first n elements of the list.  See also 'genericTake'. -}+    take :: Int -> full -> full+    take = genericTake++    {- | Drops the first n elements of the list.  See also 'genericDrop' -}+    drop :: Int -> full -> full+    drop = genericDrop++    {- | Equivalent to @('take' n xs, 'drop' n xs)@.  See also 'genericSplitAt'. -}+    splitAt :: Int -> full -> (full, full)+    splitAt = genericSplitAt++    {- | Returns all elements at start of list that satisfy the function. -}+    takeWhile :: (item -> Bool) -> full -> full+    takeWhile func l +        | null l = empty+        | func x = cons x (takeWhile func (tail l))+        | otherwise = empty+        where x = head l++    {- | Drops all elements form the start of the list that satisfy the+       function. -}+    dropWhile :: (item -> Bool) -> full -> full+    dropWhile func l+        | null l = empty+        | func (head l) = dropWhile func (tail l)+        | otherwise = l++    {- | The equivalent of @('takeWhile' f xs, 'dropWhile' f xs)@ -}+    span :: (item -> Bool) -> full -> (full, full)+    span func l+        | null l = (empty, empty)+        | func x = (cons x ys, zs) +        | otherwise = (empty, l)+       where (ys, zs) = span func (tail l)+             x = head l+    {- | The equivalent of @'span' ('not' . f)@ -}+    break :: (item -> Bool) -> full -> (full, full)+    break p = span (not . p)++    {- | Split a list into sublists, each which contains equal arguments.+       For order-preserving types, concatenating these sublists will produce+       the original list. See also 'groupBy'. -}+    group :: (ListLike full' full, Eq item) => full -> full'+    group = groupBy (==)++    {- | All initial segments of the list, shortest first -}+    inits :: (ListLike full' full) => full -> full'+    inits l+        | null l = singleton empty+        | otherwise =+            append (singleton empty)+                   (map (cons (head l)) theinits)+            where theinits = asTypeOf (inits (tail l)) [l]++    {- | All final segnemts, longest first -}+    tails :: ListLike full' full => full -> full'+    tails l+        | null l = singleton empty+        | otherwise = cons l (tails (tail l))++    ------------------------------ Predicates+    {- | True when the first list is at the beginning of the second. -}+    isPrefixOf :: Eq item => full -> full -> Bool+    isPrefixOf needle haystack+        | null needle = True+        | null haystack = False+        | otherwise = (head needle) == (head haystack) && +                      isPrefixOf (tail needle) (tail haystack)++    {- | True when the first list is at the beginning of the second. -}+    isSuffixOf :: Eq item => full -> full -> Bool+    isSuffixOf needle haystack = isPrefixOf (reverse needle) (reverse haystack)++    {- | True when the first list is wholly containted within the second -}+    isInfixOf :: Eq item => full -> full -> Bool+    isInfixOf needle haystack = +        any (isPrefixOf needle) thetails+        where thetails = asTypeOf (tails haystack) [haystack]++    ------------------------------ Searching+    {- | True if the item occurs in the list -}+    elem :: Eq item => item -> full -> Bool+    elem i = any (== i)++    {- | True if the item does not occur in the list -}+    notElem :: Eq item => item -> full -> Bool+    notElem i = all (/= i)++    {- | Take a function and return the first matching element, or Nothing+       if there is no such element. -}+    find :: (item -> Bool) -> full -> Maybe item+    find f l = case findIndex f l of+                    Nothing -> Nothing+                    Just x -> Just (index l x)++    {- | Returns only the elements that satisfy the function. -}+    filter :: (item -> Bool) -> full -> full +    filter func l +        | null l = empty+        | func (head l) = cons (head l) (filter func (tail l))+        | otherwise = filter func (tail l)++    {- | Returns the lists that do and do not satisfy the function.+       Same as @('filter' p xs, 'filter' ('not' . p) xs)@ -}+    partition :: (item -> Bool) -> full -> (full, full)+    partition p xs = (filter p xs, filter (not . p) xs)++    ------------------------------ Indexing+    {- | The element at 0-based index i.  Raises an exception if i is out+         of bounds.  Like (!!) for lists. -}+    index :: full -> Int -> item+    index l i +        | null l = error "index: index not found"+        | i < 0 = error "index: index must be >= 0"+        | i == 0 = head l+        | otherwise = index (tail l) (i - 1)++    {- | Returns the index of the element, if it exists. -}+    elemIndex :: Eq item => item -> full -> Maybe Int+    elemIndex e l = findIndex (== e) l++    {- | Returns the indices of the matching elements.  See also +       'findIndices' -}+    elemIndices :: (Eq item, ListLike result Int) => item -> full -> result+    elemIndices i l = findIndices (== i) l++    {- | Take a function and return the index of the first matching element,+         or Nothing if no element matches -}+    findIndex :: (item -> Bool) -> full -> Maybe Int+    findIndex f = listToMaybe . findIndices f++    {- | Returns the indices of all elements satisfying the function -}+    findIndices :: (ListLike result Int) => (item -> Bool) -> full -> result+    findIndices p xs = map snd $ filter (p . fst) $ thezips+        where thezips = asTypeOf (zip xs [0..]) [(head xs, 0::Int)]++    ------------------------------ Monadic operations+    {- | Evaluate each action in the sequence and collect the results -}+    sequence :: (Monad m, ListLike fullinp (m item)) =>+                fullinp -> m full+    sequence l = foldr func (return empty) l+        where func litem results = +                do x <- litem+                   xs <- results+                   return (cons x xs)++    {- | A map in monad space.  Same as @'sequence' . 'map'@ +         +         See also 'rigidMapM' -}+    mapM :: (Monad m, ListLike full' item') => +            (item -> m item') -> full -> m full'+    mapM func l = sequence mapresult+            where mapresult = asTypeOf (map func l) []++    {- | Like 'mapM', but without the possibility of changing the type+         of the item.  This can have performance benefits with some types. -}+    rigidMapM :: Monad m => (item -> m item) -> full -> m full+    rigidMapM = mapM+            +    {- | A map in monad space, discarding results.  Same as+       @'sequence_' . 'map'@ -}+    mapM_ :: (Monad m) => (item -> m b) -> full -> m ()+    mapM_ func l = sequence_ mapresult+            where mapresult = asTypeOf (map func l) []+++    ------------------------------ "Set" operations+    {- | Removes duplicate elements from the list.  See also 'nubBy' -}+    nub :: Eq item => full -> full+    nub = nubBy (==)++    {- | Removes the first instance of the element from the list.+       See also 'deleteBy' -}+    delete :: Eq item => item -> full -> full+    delete = deleteBy (==)++    {- | List difference.  Removes from the first list the first instance+       of each element of the second list.  See '(\\)' and 'deleteFirstsBy' -}+    deleteFirsts :: Eq item => full -> full -> full+    deleteFirsts = foldl (flip delete)++    {- | List union: the set of elements that occur in either list.+         Duplicate elements in the first list will remain duplicate.+         See also 'unionBy'. -}+    union :: Eq item => full -> full -> full+    union = unionBy (==)++    {- | List intersection: the set of elements that occur in both lists.+         See also 'intersectBy' -}+    intersect :: Eq item => full -> full -> full+    intersect = intersectBy (==)++    ------------------------------ Ordered lists+    {- | Sorts the list.  On data types that do not preserve ordering,+         or enforce their own ordering, the result may not be what+         you expect.  See also 'sortBy'. -}+    sort :: Ord item => full -> full+    sort = sortBy compare++    {- | Inserts the itement at the last place where it is still less than or+         equal to the next itement.  On data types that do not preserve +         ordering, or enforce their own ordering, the result may not+         be what you expect.  On types such as maps, this may result in+         changing an existing item.  See also 'insertBy'. -}+    insert :: Ord item => item -> full -> full +    insert = insertBy compare++    ------------------------------ Conversions++    {- | Converts the structure to a list.  This is logically equivolent+         to 'fromListLike', but may have a more optimized implementation. -}+    toList :: full -> [item]+    toList = fromListLike++    {- | Generates the structure from a list. -}+    fromList :: [item] -> full +    fromList [] = empty+    fromList (x:xs) = cons x (fromList xs)++    {- | Converts one ListLike to another.  See also 'toList'.+         Default implementation is @fromListLike = map id@ -}+    fromListLike :: ListLike full' item => full -> full'+    fromListLike = map id++    ------------------------------ Generalized functions+    {- | Generic version of 'nub' -}+    nubBy :: (item -> item -> Bool) -> full -> full+    nubBy f l+        | null l = empty+        | otherwise =+            cons (head l) (nubBy f (filter (\y -> not (f (head l) y)) (tail l)))++    {- | Generic version of 'deleteBy' -}+    deleteBy :: (item -> item -> Bool) -> item -> full -> full+    deleteBy func i l+        | null l = empty+        | otherwise =+            if func i (head l)+               then tail l+               else cons (head l) (deleteBy func i (tail l))++    {- | Generic version of 'deleteFirsts' -}+    deleteFirstsBy :: (item -> item -> Bool) -> full -> full -> full+    deleteFirstsBy func = foldl (flip (deleteBy func))++    {- | Generic version of 'union' -}+    unionBy :: (item -> item -> Bool) -> full -> full -> full+    unionBy func x y =+        append x $ foldl (flip (deleteBy func)) (nubBy func y) x++    {- | Generic version of 'intersect' -}+    intersectBy :: (item -> item -> Bool) -> full -> full -> full+    intersectBy func xs ys = filter (\x -> any (func x) ys) xs++    {- | Generic version of 'group'. -}+    groupBy :: (ListLike full' full, Eq item) => +                (item -> item -> Bool) -> full -> full'+    groupBy eq l+        | null l = empty+        | otherwise = cons (cons x ys) (groupBy eq zs)+                      where (ys, zs) = span (eq x) xs+                            x = head l+                            xs = tail l++    {- | Sort function taking a custom comparison function -}+    sortBy :: Ord item => (item -> item -> Ordering) -> full -> full +    sortBy cmp = foldr (insertBy cmp) empty++    {- | Like 'insert', but with a custom comparison function -}+    insertBy :: Ord item => (item -> item -> Ordering) -> item ->+                full -> full +    insertBy cmp x ys+        | null ys = singleton x+        | otherwise = case cmp x (head ys) of+                        GT -> cons (head ys) (insertBy cmp x (tail ys))+                        _ ->  cons x ys++    ------------------------------ Generic Operations+    {- | Length of the list -}+    genericLength :: Num a => full -> a+    genericLength l = calclen 0 l+        where calclen accum cl =+                  if null cl+                     then accum+                     else calclen (accum + 1) (tail cl)++    {- | Generic version of 'take' -}+    genericTake :: Integral a => a -> full -> full+    genericTake n l+        | n <= 0 = empty+        | null l = empty+        | otherwise = cons (head l) (genericTake (n - 1) (tail l))++    {- | Generic version of 'drop' -}+    genericDrop :: Integral a => a -> full -> full+    genericDrop n l +        | n <= 0 = l+        | null l = l+        | otherwise = genericDrop (n - 1) (tail l)++    {- | Generic version of 'splitAt' -}+    genericSplitAt :: Integral a => a -> full -> (full, full)+    genericSplitAt n l = (genericTake n l, genericDrop n l)++    {- | Generic version of 'replicate' -}+    genericReplicate :: Integral a => a -> item -> full+    genericReplicate count x +        | count <= 0 = empty+        | otherwise = map (\_ -> x) [1..count]++{-+instance (ListLike full item) => Monad full where+    m >>= k = foldr (append . k) empty m+    m >> k = foldr (append . (\_ -> k)) empty m+    return x = singleton x+    fail _ = empty++instance (ListLike full item) => M.MonadPlus full where+    mzero = empty+    mplus = append+-}++{- | An extension to 'ListLike' for those data types that are capable+of dealing with infinite lists.  Some 'ListLike' functions are capable+of working with finite or infinite lists.  The functions here require+infinite list capability in order to work at all. -}+class (ListLike full item) => InfiniteListLike full item | full -> item where+    {- | An infinite list of repeated calls of the function to args -}+    iterate :: (item -> item) -> item -> full+    iterate f x = cons x (iterate f (f x))++    {- | An infinite list where each element is the same -}+    repeat :: item -> full+    repeat x = xs+        where xs = cons x xs++    {- | Converts a finite list into a circular one -}+    cycle :: full -> full+    cycle xs +        | null xs = error "ListLike.cycle: empty list"+        | otherwise = xs' where xs' = append xs xs'++--------------------------------------------------+-- This instance is here due to some default class functions++instance ListLike [a] a where+    empty = []+    singleton x = [x]+    cons x l = x : l+    snoc l x = l ++ [x]+    append = (++)+    head = L.head+    last = L.last+    tail = L.tail+    init = L.init+    null = L.null+    length = L.length+    map f = fromList . L.map f+    rigidMap = L.map+    reverse = L.reverse+    intersperse = L.intersperse+    toList = id+    fromList = id+    -- fromListLike = toList+    concat = L.concat . toList+    -- concatMap func = fromList . L.concatMap func+    rigidConcatMap = L.concatMap+    any = L.any+    all = L.all+    maximum = L.maximum+    minimum = L.minimum+    -- fold+    -- foldMap+    replicate = L.replicate+    take = L.take+    drop = L.drop+    splitAt = L.splitAt+    takeWhile = L.takeWhile+    dropWhile = L.dropWhile+    span = L.span+    break = L.break+    group = fromList . L.group+    inits = fromList . L.inits+    tails = fromList . L.tails+    isPrefixOf = L.isPrefixOf+    isSuffixOf = L.isSuffixOf+    isInfixOf = L.isInfixOf+    elem = L.elem+    notElem = L.notElem+    find = L.find+    filter = L.filter+    partition = L.partition+    index = (L.!!)+    elemIndex = L.elemIndex+    elemIndices item = fromList . L.elemIndices item+    findIndex = L.findIndex+    sequence = M.sequence . toList+    -- mapM = M.mapM+    mapM_ = M.mapM_+    nub = L.nub+    delete = L.delete+    deleteFirsts = (L.\\)+    union = L.union+    intersect = L.intersect+    sort = L.sort+    groupBy func = fromList . L.groupBy func+    unionBy = L.unionBy+    intersectBy = L.intersectBy+    sortBy = L.sortBy+    insert = L.insert+++--------------------------------------------------+-- These utils are here instead of in Utils.hs because they are needed+-- by default class functions++{- | Takes two lists and returns a list of corresponding pairs. -}+zip :: (ListLike full item,+          ListLike fullb itemb,+          ListLike result (item, itemb)) =>+          full -> fullb -> result+zip = zipWith (\a b -> (a, b))++{- | Takes two lists and combines them with a custom combining function -}+zipWith :: (ListLike full item,+            ListLike fullb itemb,+            ListLike result resultitem) =>+            (item -> itemb -> resultitem) -> full -> fullb -> result+zipWith f a b+    | null a = empty+    | null b = empty+    | otherwise = cons (f (head a) (head b)) (zipWith f (tail a) (tail b))++{- | Evaluate each action, ignoring the results -}+sequence_ :: (Monad m, ListLike mfull (m item)) => mfull -> m ()+sequence_ l = foldr (>>) (return ()) l++
+ src/Data/ListLike/FoldableLL.hs view
@@ -0,0 +1,100 @@+{-+Copyright (C) 2007 John Goerzen <jgoerzen@complete.org>++All rights reserved.++For license and copyright information, see the file COPYRIGHT+-}++{- |+   Module     : Data.ListLike.FoldableLL+   Copyright  : Copyright (C) 2007 John Goerzen+   License    : LGPL++   Maintainer : John Goerzen <jgoerzen@complete.org>+   Stability  : provisional+   Portability: portable++Generic tools for data structures that can be folded.++Written by John Goerzen, jgoerzen\@complete.org++-}+module Data.ListLike.FoldableLL +    (-- * FoldableLL Class+     FoldableLL(..),+     -- * Utilities+     fold, foldMap+    ) where +import Prelude hiding (foldl, foldr, foldr1)+import qualified Data.Foldable as F+import Data.Monoid+import Data.Maybe+import qualified Data.List as L++{- | This is the primary class for structures that are to be considered +foldable.  A minimum complete definition provides 'foldl' and 'foldr'.++Instances of 'FoldableLL' can be folded, and can be many and varied.++These functions are used heavily in "Data.ListLike". -}+class FoldableLL full item | full -> item where+    {- | Left-associative fold -}+    foldl :: (a -> item -> a) -> a -> full -> a++    {- | Strict version of 'foldl'. -}+    foldl' :: (a -> item -> a) -> a -> full -> a+    -- This implementation from Data.Foldable+    foldl' f a xs = foldr f' id xs a+        where f' x k z = k $! f z x++    -- | A variant of 'foldl' with no base case.  Requires at least 1+    -- list element.+    foldl1 :: (item -> item -> item) -> full -> item+    -- This implementation from Data.Foldable+    foldl1 f xs = fromMaybe (error "fold1: empty structure")+                    (foldl mf Nothing xs)+           where mf Nothing y = Just y+                 mf (Just x) y = Just (f x y)+    {- | Right-associative fold -}+    foldr :: (item -> b -> b) -> b -> full -> b++    -- | Strict version of 'foldr'+    foldr' :: (item -> b -> b) -> b -> full -> b+    -- This implementation from Data.Foldable+    foldr' f a xs = foldl f' id xs a+        where f' k x z = k $! f x z++    -- | Like 'foldr', but with no starting value+    foldr1 :: (item -> item -> item) -> full -> item+    -- This implementation from Data.Foldable+    foldr1 f xs = fromMaybe (error "foldr1: empty structure")+                    (foldr mf Nothing xs)+           where mf x Nothing = Just x+                 mf x (Just y) = Just (f x y)++{- | Combine the elements of a structure using a monoid.+     @'fold' = 'foldMap' id@ -}+fold :: (FoldableLL full item, Monoid item) => full -> item+fold = foldMap id++{- | Map each element to a monoid, then combine the results -}+foldMap :: (FoldableLL full item, Monoid m) => (item -> m) -> full -> m+foldMap f = foldr (mappend . f) mempty++instance FoldableLL [a] a where+    foldl = L.foldl+    foldl1 = L.foldl1+    foldl' = L.foldl'+    foldr = L.foldr+    foldr1 = L.foldr1+    foldr' = F.foldr'+{-+instance (F.Foldable f) => FoldableLL (f a) a where+    foldl = F.foldl+    foldl1 = F.foldl1+    foldl' = F.foldl'+    foldr = F.foldr+    foldr1 = F.foldr1+    foldr' = F.foldr'+-}
+ src/Data/ListLike/IO.hs view
@@ -0,0 +1,125 @@+{-+Copyright (C) 2007 John Goerzen <jgoerzen@complete.org>++All rights reserved.++For license and copyright information, see the file COPYRIGHT++-}++{- |+   Module     : Data.ListLike.IO+   Copyright  : Copyright (C) 2007 John Goerzen+   License    : LGPL++   Maintainer : John Goerzen <jgoerzen@complete.org>+   Stability  : provisional+   Portability: portable++String-like functions++Written by John Goerzen, jgoerzen\@complete.org+-}++module Data.ListLike.IO+    ( ListLikeIO(..)+    )+       where+import Prelude hiding (length, head, last, null, tail, map, filter, concat, +                       any, lookup, init, all, foldl, foldr, foldl1, foldr1,+                       maximum, minimum, iterate, span, break, takeWhile,+                       dropWhile, reverse, zip, zipWith, sequence,+                       sequence_, mapM, mapM_, concatMap, and, or, sum,+                       product, repeat, replicate, cycle, take, drop,+                       splitAt, elem, notElem, unzip, lines, words,+                       unlines, unwords, putStr, getContents)+import qualified System.IO as IO+import Data.ListLike.Base++{- | An extension to 'ListLike' for those data types that support+I\/O.  These functions mirror those in "System.IO" for the most part.  They+also share the same names; see the comments in "Data.ListLike" for help+importing them.++Note that some types may not be capable of lazy reading or writing.+Therefore, the usual semantics of "System.IO" functions regarding laziness+may or may not be available from a particular implementation.+    +Minimal complete definition:++* hGetLine++* hGetContents++* hGet++* hGetNonBlocking++* hPutStr+-}+class (ListLike full item) => ListLikeIO full item | full -> item where+    {- | Reads a line from the specified handle -}+    hGetLine :: IO.Handle -> IO full++    -- | Read entire handle contents.  May be done lazily like+    -- 'System.IO.hGetContents'.+    hGetContents :: IO.Handle -> IO full++    -- | Read specified number of bytes.  See 'System.IO.hGet' for+    -- particular semantics.+    hGet :: IO.Handle -> Int -> IO full++    -- | Non-blocking read.  See 'System.IO.hGetNonBlocking' for more.+    hGetNonBlocking :: IO.Handle -> Int -> IO full++    -- | Writing entire data.+    hPutStr :: IO.Handle -> full -> IO ()++    -- | Write data plus newline character.+    hPutStrLn :: IO.Handle -> full -> IO ()+    hPutStrLn fp x =+        do hPutStr fp x+           IO.hPutStrLn fp ""++    -- | Read one line+    getLine :: IO full+    getLine = hGetLine IO.stdin++    -- | Read entire content from stdin.  See 'hGetContents'.+    getContents :: IO full+    getContents = hGetContents IO.stdin++    -- | Write data to stdout.+    putStr :: full -> IO ()+    putStr = hPutStr IO.stdout++    -- | Write data plus newline character to stdout.+    putStrLn :: full -> IO ()+    putStrLn = hPutStrLn IO.stdout++    -- | Interact with stdin and stdout by using a function to transform+    -- input to output.  May be lazy.  See 'System.IO.interact' for more.+    interact :: (full -> full) -> IO ()+    interact func = +        do c <- getContents+           putStr (func c)++    -- | Read file.  May be lazy.+    readFile :: FilePath -> IO full+    readFile fn =+        do fp <- IO.openFile fn IO.ReadMode+           hGetContents fp++    -- | Write data to file.+    writeFile :: FilePath -> full -> IO ()+    writeFile fn x =+        do fp <- IO.openFile fn IO.WriteMode+           hPutStr fp x+           IO.hClose fp++    -- | Append data to file.+    appendFile :: FilePath -> full -> IO ()+    appendFile fn x =+        do fp <- IO.openFile fn IO.AppendMode+           hPutStr fp x+           IO.hClose fp
+ src/Data/ListLike/Instances.hs view
@@ -0,0 +1,542 @@+{-+Copyright (C) 2007 John Goerzen <jgoerzen@complete.org>++All rights reserved.++For license and copyright information, see the file COPYRIGHT++-}++{- |+   Module     : Data.ListLike.Instances+   Copyright  : Copyright (C) 2007 John Goerzen+   License    : LGPL++   Maintainer : John Goerzen <jgoerzen@complete.org>+   Stability  : provisional+   Portability: portable++Instances of 'Data.ListLike.ListLike' and related classes.+Re-exported by "Data.ListLike".++Written by John Goerzen, jgoerzen\@complete.org+-}++module Data.ListLike.Instances () where+import Prelude hiding (length, head, last, null, tail, map, filter, concat, +                       any, lookup, init, all, foldl, foldr, foldl1, foldr1,+                       maximum, minimum, iterate, span, break, takeWhile,+                       dropWhile, reverse, zip, zipWith, sequence,+                       sequence_, mapM, mapM_, concatMap, and, or, sum,+                       product, repeat, replicate, cycle, take, drop,+                       splitAt, elem, notElem, unzip, lines, words,+                       unlines, unwords)+import qualified Data.List as L+import Data.ListLike.Base+import Data.ListLike.String+import Data.ListLike.IO+import Data.ListLike.FoldableLL+import Data.Int+import Data.Monoid+import qualified Data.ByteString as BS+import qualified Data.Foldable as F+import qualified Data.Array.IArray as A+import Data.Array.IArray((!), (//), Ix(..))+import qualified Data.ByteString.Lazy as BSL+import qualified System.IO as IO+import Data.Word+import qualified Data.Map as Map++--------------------------------------------------+-- []++-- Basic list instance is in Base.hs+-- FoldableLL instance implied by Foldable++instance ListLikeIO String Char where+    hGetLine = IO.hGetLine+    hGetContents = IO.hGetContents+    hGet h c = BSL.hGet h c >>= (return . toString)+    hGetNonBlocking h i = BSL.hGetNonBlocking h i >>= (return . toString)+    hPutStr = IO.hPutStr+    hPutStrLn = IO.hPutStrLn+    getLine = IO.getLine+    getContents = IO.getContents+    putStr = IO.putStr+    putStrLn = IO.putStrLn+    interact = IO.interact+    readFile = IO.readFile+    writeFile = IO.writeFile++instance StringLike String where+    toString = id+    fromString = id++instance InfiniteListLike [a] a where+    iterate = L.iterate+    repeat = L.repeat+    cycle = L.cycle++--------------------------------------------------+-- ByteString++instance FoldableLL BS.ByteString Word8 where+    foldl = BS.foldl+    foldl' = BS.foldl'+    foldl1 = BS.foldl1+    foldr = BS.foldr+    foldr' = BS.foldr'+    foldr1 = BS.foldr1++instance ListLike BS.ByteString Word8 where+    empty = BS.empty+    singleton = BS.singleton+    cons = BS.cons+    snoc = BS.snoc+    append = BS.append+    head = BS.head+    last = BS.last+    tail = BS.tail+    init = BS.init+    null = BS.null+    length = BS.length+    -- map = BS.map+    rigidMap = BS.map+    reverse = BS.reverse+    intersperse = BS.intersperse+    concat = BS.concat . toList+    --concatMap = BS.concatMap+    rigidConcatMap = BS.concatMap+    any = BS.any+    all = BS.all+    maximum = BS.maximum+    minimum = BS.minimum+    replicate = BS.replicate+    take = BS.take+    drop = BS.drop+    splitAt = BS.splitAt+    takeWhile = BS.takeWhile+    dropWhile = BS.dropWhile+    span = BS.span+    break = BS.break+    group = fromList . BS.group+    inits = fromList . BS.inits+    tails = fromList . BS.tails+    isPrefixOf = BS.isPrefixOf+    isSuffixOf = BS.isSuffixOf+    --isInfixOf = BS.isInfixOf+    elem = BS.elem+    notElem = BS.notElem+    find = BS.find+    filter = BS.filter+    --partition = BS.partition+    index = BS.index+    elemIndex = BS.elemIndex+    elemIndices x = fromList . BS.elemIndices x+    findIndex = BS.findIndex+    findIndices x = fromList . BS.findIndices x+    --sequence = BS.sequence+    --mapM = BS.mapM+    --mapM_ = BS.mapM_+    --nub = BS.nub+    --delete = BS.delete+    --deleteFirsts = BS.deleteFirsts+    --union = BS.union+    --intersect = BS.intersect+    sort = BS.sort+    --insert = BS.insert+    toList = BS.unpack+    fromList = BS.pack+    fromListLike = fromList . toList+    --nubBy = BS.nubBy+    --deleteBy = BS.deleteBy+    --deleteFirstsBy = BS.deleteFirstsBy+    --unionBy = BS.unionBy+    --intersectBy = BS.intersectBy+    groupBy f = fromList . BS.groupBy f+    --sortBy = BS.sortBy+    --insertBy = BS.insertBy+    genericLength = fromInteger . fromIntegral . BS.length+    genericTake i = BS.take (fromIntegral i)+    genericDrop i = BS.drop (fromIntegral i)+    genericSplitAt i = BS.splitAt (fromIntegral i)+    genericReplicate i = BS.replicate (fromIntegral i)++instance ListLikeIO BS.ByteString Word8 where+    hGetLine = BS.hGetLine+    hGetContents = BS.hGetContents+    hGet = BS.hGet+    hGetNonBlocking = BS.hGetNonBlocking+    hPutStr = BS.hPutStr+    hPutStrLn = BS.hPutStrLn+    getLine = BS.getLine+    getContents = BS.getContents+    putStr = BS.putStr+    putStrLn = BS.putStrLn+    interact = BS.interact+    readFile = BS.readFile+    writeFile = BS.writeFile+    appendFile = BS.appendFile++instance StringLike BS.ByteString where+    toString = map (toEnum . fromIntegral) . BS.unpack+    fromString = BS.pack . map (fromIntegral . fromEnum)++--------------------------------------------------+-- ByteString.Lazy++instance FoldableLL BSL.ByteString Word8 where+    foldl = BSL.foldl+    foldl' = BSL.foldl'+    foldl1 = BSL.foldl1+    foldr = BSL.foldr+    --foldr' = BSL.foldr'+    foldr1 = BSL.foldr1++mi64toi :: Maybe Int64 -> Maybe Int+mi64toi Nothing = Nothing+mi64toi (Just x) = Just (fromIntegral x)++instance ListLike BSL.ByteString Word8 where+    empty = BSL.empty+    singleton = BSL.singleton+    cons = BSL.cons+    snoc = BSL.snoc+    append = BSL.append+    head = BSL.head+    last = BSL.last+    tail = BSL.tail+    init = BSL.init+    null = BSL.null+    length = fromIntegral . BSL.length+    -- map = BSL.map+    rigidMap = BSL.map+    reverse = BSL.reverse+    --intersperse = BSL.intersperse+    concat = BSL.concat . toList+    --concatMap = BSL.concatMap+    rigidConcatMap = BSL.concatMap+    any = BSL.any+    all = BSL.all+    maximum = BSL.maximum+    minimum = BSL.minimum+    replicate i = BSL.replicate (fromIntegral i)+    take i = BSL.take (fromIntegral i)+    drop i = BSL.drop (fromIntegral i)+    splitAt i = BSL.splitAt (fromIntegral i)+    takeWhile = BSL.takeWhile+    dropWhile = BSL.dropWhile+    span = BSL.span+    break = BSL.break+    group = fromList . BSL.group+    inits = fromList . BSL.inits+    tails = fromList . BSL.tails+    isPrefixOf = BSL.isPrefixOf+    --isSuffixOf = BSL.isSuffixOf+    --isInfixOf = BSL.isInfixOf+    elem = BSL.elem+    notElem = BSL.notElem+    find = BSL.find+    filter = BSL.filter+    --partition = BSL.partition+    index l i = BSL.index l (fromIntegral i)+    elemIndex i = mi64toi . BSL.elemIndex i +    --elemIndices x = fromList . L.map fromIntegral . BSL.elemIndices x+    findIndex f = mi64toi . BSL.findIndex f+    --findIndices x = fromList . L.map fromIntegral . BSL.findIndices x+    --sequence = BSL.sequence+    --mapM = BSL.mapM+    --mapM_ = BSL.mapM_+    --nub = BSL.nub+    --delete = BSL.delete+    --deleteFirsts = BSL.deleteFirsts+    --union = BSL.union+    --intersect = BSL.intersect+    --sort = BSL.sort+    --insert = BSL.insert+    toList = BSL.unpack+    fromList = BSL.pack+    fromListLike = fromList . toList+    --nubBy = BSL.nubBy+    --deleteBy = BSL.deleteBy+    --deleteFirstsBy = BSL.deleteFirstsBy+    --unionBy = BSL.unionBy+    --intersectBy = BSL.intersectBy+    -- BSL.groupBy is broken. groupBy f = fromList . BSL.groupBy f+    -- the below works on ghc but generates a type error on hugs+    -- groupBy func = map fromList . L.groupBy func . toList+    --sortBy = BSL.sortBy+    --insertBy = BSL.insertBy+    genericLength = fromInteger . fromIntegral . BSL.length+    genericTake i = BSL.take (fromIntegral i)+    genericDrop i = BSL.drop (fromIntegral i)+    genericSplitAt i = BSL.splitAt (fromIntegral i)+    genericReplicate i = BSL.replicate (fromIntegral i)++strict2lazy :: BS.ByteString -> IO BSL.ByteString+strict2lazy b = return (BSL.fromChunks [b])+instance ListLikeIO BSL.ByteString Word8 where+    hGetLine h = BS.hGetLine h >>= strict2lazy+    hGetContents = BSL.hGetContents+    hGet = BSL.hGet+    hGetNonBlocking = BSL.hGetNonBlocking+    hPutStr = BSL.hPut+    --hPutStrLn = BSL.hPutStrLn+    getLine = BS.getLine >>= strict2lazy+    getContents = BSL.getContents+    putStr = BSL.putStr+    putStrLn = BSL.putStrLn+    interact = BSL.interact+    readFile = BSL.readFile+    writeFile = BSL.writeFile+    appendFile = BSL.appendFile++instance StringLike BSL.ByteString where+    toString = map (toEnum . fromIntegral) . BSL.unpack+    fromString = BSL.pack . map (fromIntegral . fromEnum)++--------------------------------------------------+-- Map++instance (Ord key) => FoldableLL (Map.Map key val) (key, val) where+    foldr f start m = Map.foldWithKey func start m+            where func k v accum = f (k, v) accum+    foldl f start m = L.foldl f start (Map.toList m)++l2m :: (Ord k, Ord k2) => ([(k, v)], [(k2, v2)]) -> (Map.Map k v, Map.Map k2 v2)+l2m (l1, l2) = (Map.fromList l1, Map.fromList l2)+instance (Ord key, Eq val) => ListLike (Map.Map key val) (key, val) where+    empty = Map.empty+    singleton (k, v) = Map.singleton k v+    cons (k, v) m = Map.insert k v m+    snoc = flip cons+    append = Map.union+    head = Map.elemAt 0+    last m = Map.elemAt (Map.size m - 1) m+    -- was deleteAt 0, but that is broken in GHC 6.6+    tail = drop 1+    -- broken in GHC 6.6: init m = Map.deleteAt (Map.size m - 1) m+    init = Map.fromAscList . L.init . Map.toAscList+    null = Map.null+    length = Map.size+    map f = fromList . map f . Map.toList+    rigidMap f = Map.fromList . L.map f . Map.toList+    reverse = id+    intersperse i f+        | Map.size f <= 1 = f+        | otherwise = cons i f+    -- concat+    -- concatMap+    -- rigidConcatMap+    -- any+    -- all+    -- maximum+    -- minimum+    replicate = genericReplicate+    take n = Map.fromAscList . L.take n . Map.toAscList+    drop n = Map.fromAscList . L.drop n . Map.toAscList+    splitAt n = l2m . L.splitAt n . Map.toList+    takeWhile f = Map.fromAscList . L.takeWhile f . Map.toAscList+    dropWhile f = Map.fromAscList . L.dropWhile f . Map.toAscList+    span f = l2m . L.span f . Map.toList+    break f = span (not . f)+    group m+        | null m = empty+        | otherwise = cons (singleton (head m)) (group (tail m))+    -- group+    -- inits+    -- tails+    isPrefixOf f1 f2 = L.isPrefixOf (Map.toList f1) (Map.toList f2)+    isSuffixOf f1 f2 = L.isSuffixOf (Map.toList f1) (Map.toList f2)+    isInfixOf = Map.isSubmapOf+    --elem = Map.member+    --notElem = Map.notMember+    -- find+    filter f m = Map.filterWithKey func m+            where func k v = f (k, v)+    index = flip Map.elemAt+    elemIndex (k, v) m =+        case Map.lookupIndex k m of+             Nothing -> fail "elemIndex: no matching key"+             Just i -> if snd (Map.elemAt i m) == v+                           then Just i+                           else fail "elemIndex on Map: matched key but not value"+    elemIndices i m = +        case elemIndex i m of+             Nothing -> empty+             Just x -> singleton x+    -- findIndex+    -- findIndices+    -- sequence+    -- mapM+    -- rigidMapM+    -- mapM_+    nub = id+    delete (k, v) m =+        case Map.lookup k m of+             Nothing -> m+             Just x -> if x == v+                          then Map.delete k m+                          else m+    union = Map.union+    -- intersect+    sort = id+    insert = cons+    toList = Map.toList+    fromList = Map.fromList+    nubBy func = Map.fromAscList . L.nubBy func . Map.toAscList+    --deleteBy+    deleteFirstsBy func m1 m2 = Map.fromAscList $ +                                L.deleteFirstsBy func (Map.toAscList m1)+                                                 (Map.toAscList m2)+    --deleteFirstsBy+    unionBy func m1 m2 = Map.fromList $ +                            L.unionBy func (Map.toList m1) (Map.toList m2)+    --intersectBy+    --groupBy+    sortBy _ = id+    insertBy _ = insert+    genericLength = fromIntegral . Map.size+    genericTake n = Map.fromAscList . L.genericTake n . Map.toAscList+    genericDrop n = Map.fromAscList . L.genericDrop n . Map.toAscList+    genericSplitAt n = l2m . L.genericSplitAt n . Map.toList+    genericReplicate count item+        | count <= 0 = empty+        | otherwise = singleton item++--------------------------------------------------+-- Arrays++instance (Ix i) => FoldableLL (A.Array i e) e where+    foldl = F.foldl+    foldl1 = F.foldl1+    foldl' = F.foldl'+    foldr = F.foldr+    foldr1 = F.foldr1+    foldr' = F.foldr'++instance (Integral i, Ix i) => Monoid (A.Array i e) where+    mempty = A.listArray (0, -1) []+    mappend l1 l2 =+        A.array (blow, newbhigh)+              (A.assocs l1 ++ zip [(bhigh + 1)..newbhigh] (A.elems l2))+        where newlen = genericLength newelems+              newelems = A.elems l2+              newbhigh = bhigh + newlen+              (blow, bhigh) = A.bounds l1++instance (Integral i, Ix i) => ListLike (A.Array i e) e where+    empty = mempty+    singleton i = A.listArray (0, 0) [i]+    cons i l = +        -- To add something to the beginning of an array, we must+        -- change the bounds and set the first element.+        (A.ixmap (blow - 1, bhigh) id l) // [(blow - 1, i)]+        where (blow, bhigh) = A.bounds l+    snoc l i = +        -- Here we must change the bounds and set the last element+        (A.ixmap (blow, bhigh + 1) id l) // [(bhigh + 1, i)]+        where (blow, bhigh) = A.bounds l+    append = mappend+    head l = l ! (fst (A.bounds l))+    last l = l ! (snd (A.bounds l))+    tail l = A.array (blow + 1, bhigh) (tail (A.assocs l))+            where (blow, bhigh) = A.bounds l+    init l = A.array (blow, bhigh - 1) (init (A.assocs l))+            where (blow, bhigh) = A.bounds l+    null l = genericLength l == (0::Integer)+    length = genericLength+    -- map+    rigidMap = A.amap+    reverse l = A.listArray (A.bounds l) (L.reverse (A.elems l)) +    -- intersperse+    -- concat+    -- concatMap+    -- rigidConcatMap+    any x = L.any x . A.elems+    all x = L.all x . A.elems+    maximum = L.maximum . A.elems+    minimum = L.minimum . A.elems+    replicate = genericReplicate+    take = genericTake+    drop = genericDrop+    -- splitAt+    -- takeWhile+    -- dropWhile+    -- span+    -- break+    -- group+    -- inits+    -- tails+    isPrefixOf l1 l2 = L.isPrefixOf (toList l1) (toList l2)+    isSuffixOf l1 l2 = L.isSuffixOf (toList l1) (toList l2)+    isInfixOf l1 l2 = L.isInfixOf (toList l1) (toList l2)+    elem i l = L.elem i (toList l)+    -- notElem+    filter f = fromList . L.filter f . toList+    -- partition+    index l i = l ! ((fromIntegral i) + offset)+        where offset = (fst $ A.bounds l)+    elemIndex i = L.elemIndex i . toList+    elemIndices i = fromList . L.elemIndices i . toList+    findIndex f = L.findIndex f . toList+    findIndices f = fromList . L.findIndices f . toList+    -- sequence = M.sequence . toList+    -- mapM f = M.mapM f . toList+    -- rigidMapM = mapM+    -- mapM_ f = M.mapM_ f . toList+    nub = fromList . L.nub . toList+    -- delete+    -- deleteFirsts+    -- union+    -- intersect+    sort l = A.listArray (A.bounds l) (L.sort (A.elems l))+    -- insert+    toList = A.elems+    fromList l = A.listArray (0, genericLength l - 1) l+    -- fromListLike+    nubBy f = fromList . L.nubBy f . toList+    -- deleteBy+    -- deleteFirstsBy+    -- unionBy+    -- intersectBy+    -- groupBy+    sortBy f l = A.listArray (A.bounds l) (L.sortBy f (A.elems l))+    -- insertBy+    genericLength l = fromIntegral (bhigh - blow + 1)+        where (blow, bhigh) = A.bounds l+    genericTake count l +        | count > genericLength l = l+        | count <= 0 = empty+        | otherwise = A.listArray (blow, blow + (fromIntegral count) - 1)+                          (L.genericTake count (A.elems l))+        where (blow, _) = A.bounds l+    genericDrop count l = A.listArray (blow + (fromIntegral count), bhigh)+                          (L.genericDrop count (A.elems l))+        where (blow, bhigh) = A.bounds l+    -- geneicSplitAt+    genericReplicate count i = A.listArray (0, (fromIntegral count) - 1) +                                           (L.genericReplicate count i)+++instance (Integral i, Ix i) => StringLike (A.Array i Char) where+    toString = toList+    fromString = fromList+    -- lines+    -- words++instance (Integral i, Ix i) => ListLikeIO (A.Array i Char) Char where+    hGetLine h = IO.hGetLine h >>= (return . fromList)+    hGetContents h = IO.hGetContents h >>= (return . fromList)+    hGet h i = ((hGet h i)::IO String) >>= (return . fromList)+    hGetNonBlocking h i = ((hGetNonBlocking h i):: IO String) >>= (return . fromList)+    hPutStr h = hPutStr h . toString+    hPutStrLn h = hPutStrLn h . toString+    getLine = IO.getLine >>= (return . fromString)+    getContents = IO.getContents >>= (return . fromString)+    putStr = IO.putStr . toString+    putStrLn = IO.putStrLn . toString+    -- interact+    -- readFile+    -- writeFile+    -- appendFile
+ src/Data/ListLike/String.hs view
@@ -0,0 +1,78 @@+{-+Copyright (C) 2007 John Goerzen <jgoerzen@complete.org>++All rights reserved.++For license and copyright information, see the file COPYRIGHT++-}++{- |+   Module     : Data.ListLike.String+   Copyright  : Copyright (C) 2007 John Goerzen+   License    : LGPL++   Maintainer : John Goerzen <jgoerzen@complete.org>+   Stability  : provisional+   Portability: portable++String-like functions++Written by John Goerzen, jgoerzen\@complete.org+-}++module Data.ListLike.String+    ( StringLike(..)+    )+       where+import Prelude hiding (length, head, last, null, tail, map, filter, concat, +                       any, lookup, init, all, foldl, foldr, foldl1, foldr1,+                       maximum, minimum, iterate, span, break, takeWhile,+                       dropWhile, reverse, zip, zipWith, sequence,+                       sequence_, mapM, mapM_, concatMap, and, or, sum,+                       product, repeat, replicate, cycle, take, drop,+                       splitAt, elem, notElem, unzip, lines, words,+                       unlines, unwords)+import qualified Data.List as L+import Data.ListLike.Base++{- | An extension to 'ListLike' for those data types that are similar+to a 'String'.  Minimal complete definition is 'toString' and+'fromString'. -}+class StringLike s where+    {- | Converts the structure to a 'String' -}+    toString :: s -> String+    +    {- | Converts a 'String' to a list -}+    fromString :: String -> s++    {- | Breaks a string into a list of strings -}+    lines :: (ListLike full s) => s -> full+    --lines = map fromString . L.lines . toString +    lines = myLines++    {- | Breaks a string into a list of words -}+    words :: ListLike full s => s -> full+    words = myWords++    {- | Joins lines -}+    unlines :: ListLike full s => full -> s+    unlines = myUnlines++    {- | Joins words -}+    unwords :: ListLike full s => full -> s+    unwords = myUnwords++-- For some reason, Hugs required splitting these out into+-- separate functions.+myLines :: (StringLike s, ListLike full s) => s -> full+myLines = map fromString . L.lines . toString++myWords :: (StringLike s, ListLike full s) => s -> full+myWords = map fromString . L.words . toString++myUnlines :: (StringLike s, ListLike full s) => full -> s+myUnlines = fromString . L.unlines . map toString++myUnwords :: (StringLike s, ListLike full s) => full -> s+myUnwords = fromString . L.unwords . map toString
+ src/Data/ListLike/Utils.hs view
@@ -0,0 +1,63 @@+{-+Copyright (C) 2007 John Goerzen <jgoerzen@complete.org>++All rights reserved.++For license and copyright information, see the file COPYRIGHT++-}++{- |+   Module     : Data.ListLike.Utils+   Copyright  : Copyright (C) 2007 John Goerzen+   License    : LGPL++   Maintainer : John Goerzen <jgoerzen@complete.org>+   Stability  : provisional+   Portability: portable++Utilities for 'Data.ListLike.ListLike' and friends.  More functions+similar to 'Data.List' but not part of the main typeclass.++Written by John Goerzen, jgoerzen\@complete.org+-}++module Data.ListLike.Utils+    (and, or, sum, product, zip, zipWith, unzip, sequence_+    ) where+import Prelude hiding (length, head, last, null, tail, map, filter, concat, +                       any, lookup, init, all, foldl, foldr, foldl1, foldr1,+                       maximum, minimum, iterate, span, break, takeWhile,+                       dropWhile, reverse, zip, zipWith, sequence,+                       sequence_, mapM, mapM_, concatMap, and, or, sum,+                       product, repeat, replicate, cycle, take, drop,+                       splitAt, elem, notElem, unzip, lines, words,+                       unlines, unwords)+import Data.ListLike.Base+import Data.ListLike.FoldableLL+import Data.Monoid++-- | Returns True if all elements are True+and :: ListLike full Bool => full -> Bool+and = all (== True)++-- | Returns True if any element is True+or :: ListLike full Bool => full -> Bool+or = any (== True)++-- | The sum of the list+sum :: (Num a, ListLike full a) => full -> a+sum = getSum . foldMap Sum++-- | The product of the list+product :: (Num a, ListLike full a) => full -> a+product = getProduct . foldMap Product++------------------------------ Zipping+-- zip, zipWith  in Base+{- | Converts a list of pairs into two separate lists of elements -}+unzip :: (ListLike full (itema, itemb),+          ListLike ra itema,+          ListLike rb itemb) => full -> (ra, rb)+unzip inp = foldr convert (empty, empty) inp+    where convert (a, b) (as, bs) = ((cons a as), (cons b bs))
+ testsrc/runtests.hs view
@@ -0,0 +1,344 @@+{-+Copyright (C) 2007 John Goerzen <jgoerzen@complete.org>++All rights reserved.++For license and copyright information, see the file COPYRIGHT++-}++import Test.QuickCheck+import Test.QuickCheck.Batch+import qualified Data.ByteString as BS+import qualified Data.Array as A+import qualified Data.ByteString.Lazy as BSL+import qualified Data.ListLike as LL+import qualified Data.Map as Map+import qualified Data.Array as A+import qualified Data.Foldable as F+import System.Random+import qualified Test.HUnit as HU+import System.IO+import Text.Printf+import Data.Word+import Data.List+import Data.Monoid+import TestInfrastructure+import Data.Foldable(foldr', fold, foldMap)+import System.Info+++-- prop_singleton :: (Eq i,LL.ListLike f i) => f -> i -> Bool+--prop_singleton :: (Eq i, LL.ListLike f i, Arbitrary f, Show f, Show i, Arbitrary i) => f -> i -> Bool+prop_singleton f x = (LL.toList $ asTypeOf (LL.singleton x) f) == [x]++prop_empty f = (LL.toList l == []) && (LL.null l) && (LL.length l == 0)+    where l = asTypeOf LL.empty f++prop_tofromlist f = +    LL.toList f == l && +    LL.length f == length l &&+    f == (LL.fromList . LL.toList $ f)+    where l = LL.toList f++prop_length f = LL.length f == length (LL.toList f)+prop_cons f i = llcmp (LL.cons i f) (i : (LL.toList f))+prop_append f1 f2 = llcmp (LL.append f1 f2) (LL.toList f1 ++ LL.toList f2)+prop_head f = not (LL.null f) ==> LL.head f == head (LL.toList f)+prop_last f = not (LL.null f) ==> LL.last f == last (LL.toList f)+prop_tail f = not (LL.null f) ==> llcmp (LL.tail f) (tail (LL.toList f))+prop_init f = not (LL.null f) ==> llcmp (LL.init f) (init (LL.toList f))+prop_null f = LL.null f == null (LL.toList f)+prop_length2 f = checkLengths f (LL.toList f)+prop_length3 f1 f2 = llcmp (LL.append f1 f2) (LL.toList f1 ++ LL.toList f2)++prop_map :: forall full item. (TestLL full item, TestLL [item] item) => full -> (item -> item) -> Result+prop_map f func = llcmp llmap (map func (LL.toList f))+    where llmap = asTypeOf (LL.map func f) (LL.toList f)++prop_rigidMap f func = llcmp (LL.rigidMap func f) (map func (LL.toList f))+prop_reverse f = llcmp (LL.reverse f) (reverse (LL.toList f))+prop_intersperse f i = llcmp (LL.intersperse i f) (intersperse i (LL.toList f))++prop_concat f = +    llcmp (LL.concat f) (concat $ map LL.toList (LL.toList f))++prop_concatmap :: forall full item. (TestLL full item, TestLL [item] item) => full -> (item -> [item]) -> Result+prop_concatmap f func =+    llcmp (LL.concatMap func f)+          (concatMap func (LL.toList f))++prop_rigidConcatMap f func =+    llcmp (LL.rigidConcatMap func f)+          (concatMap (LL.toList . func) (LL.toList f))++prop_any f func = (LL.any func f) @?= (any func (LL.toList f))+prop_all f func = (LL.all func f) @?= (all func (LL.toList f))+prop_maximum f = not (LL.null f) ==> LL.maximum f @=? maximum (LL.toList f)+prop_minimum f = not (LL.null f) ==> LL.minimum f @=? minimum (LL.toList f)+prop_replicate f count i = +    llcmp res (replicate count i)+    where res = asTypeOf (LL.replicate count i) f+prop_take f count = llcmp (LL.take count f) (take count (LL.toList f))+prop_drop f count = count >= 0 ==> llcmp (LL.drop count f) (drop count (LL.toList f))+prop_splitAt f count = count >= 0 ==>+    llcmp [(\(x, y) -> (LL.toList x, LL.toList y)) . LL.splitAt count $ f] +          [LL.splitAt count (LL.toList f)]+prop_takeWhile f func = llcmp (LL.takeWhile func f) +                              (takeWhile func (LL.toList f))+prop_dropWhile f func = llcmp (LL.dropWhile func f) +                              (dropWhile func (LL.toList f))+prop_span f func = +    llcmp [(\(x, y) -> (LL.toList x, LL.toList y)) . LL.span func $ f]+          [span func (LL.toList f)]+prop_break f func = +    llcmp [(\(x, y) -> (LL.toList x, LL.toList y)) . LL.break func $ f]+          [break func (LL.toList f)]+prop_group f =+    -- llcmp (map LL.toList (LL.group f)) (group (LL.toList f))+    (map LL.toList (LL.group f)) @?= (group (LL.toList f))+prop_inits f = (map LL.toList (LL.inits f)) @?= (inits (LL.toList f))+prop_tails f = (map LL.toList (LL.tails f)) @?= (tails (LL.toList f))+prop_isPrefixOf f1 f2 = LL.isPrefixOf f1 f2 @?= +    (isPrefixOf (LL.toList f1) (LL.toList f2))+prop_isSuffixOf f1 f2 = LL.isSuffixOf f1 f2 @?=+    (isSuffixOf (LL.toList f1) (LL.toList f2))+prop_isInfixOf f1 f2 = LL.isInfixOf f1 f2 @?=+    (isInfixOf (LL.toList f1) (LL.toList f2))+prop_elem f i = LL.elem i f @?= elem i (LL.toList f)+prop_notElem f i = LL.notElem i f @?= notElem i (LL.toList f)+prop_find f func = LL.find func f @?= find func (LL.toList f)+prop_filter f func = llcmp (LL.filter func f) (filter func (LL.toList f))+prop_partition f func = +    (LL.toList f1, LL.toList f2) @?= partition func (LL.toList f)+    where (f1, f2) = LL.partition func f+prop_index f i = (i >= 0 && i < LL.length f) ==>+    (LL.index f i @?= ((LL.toList f) !! i))+prop_elemIndex f i = LL.elemIndex i f @?= elemIndex i (LL.toList f)+prop_elemIndices f i = LL.elemIndices i f @?= elemIndices i (LL.toList f)+prop_findIndex f func = LL.findIndex func f @?= findIndex func (LL.toList f)+prop_findIndices f func =+    LL.findIndices func f @?= findIndices func (LL.toList f)++prop_sequence f =+    case (llres, sequence testit) of+         (Just ll, Just l) -> llcmp ll l+         _ -> error "Error!"+    where testit = map Just (LL.toList f)+          llres = asTypeOf (LL.sequence testit) (Just f)++prop_mapM :: forall full item. (TestLL full item, TestLL [item] item) => full -> (item -> Maybe item) -> Result+prop_mapM f func = llmapM @?= (mapM func (LL.toList f))+    where llmapM = asTypeOf (LL.mapM func f) (Just (LL.toList f))++prop_rigidMapM :: forall full item. (TestLL full item, TestLL [item] item) => full -> (item -> Maybe item) -> Result+prop_rigidMapM f func = +    case (LL.rigidMapM func f, mapM func (LL.toList f)) of+         (Just ll, Just l) -> llcmp ll l+         _ -> error "error in prop_rigidMapM"++-- FIXME: can we test mapM_?++prop_nub f = llcmp (LL.nub f) (nub (LL.toList f))+prop_delete f i = llcmp (LL.delete i f) (delete i (LL.toList f))+prop_deleteFirsts f1 f2 = llcmp (LL.deleteFirsts f1 f2) +    ((LL.toList f1) \\ (LL.toList f2))+prop_union f1 f2 = llcmp (LL.union f1 f2) +    (union (LL.toList f1) (LL.toList f2))+prop_intersect f1 f2 = llcmp (LL.intersect f1 f2) +    (intersect (LL.toList f1) (LL.toList f2))+prop_sort f1 = llcmp (LL.sort f1) (sort (LL.toList f1))+prop_insert f i = llcmp (LL.insert i f) (insert i (LL.toList f))+prop_nubBy f func = llcmp (LL.nubBy func f) (nubBy func (LL.toList f))+prop_deleteBy f func i = llcmp (LL.deleteBy func i f) +                         (deleteBy func i (LL.toList f))+prop_deleteFirstsBy f1 f2 func = llcmp (LL.deleteFirstsBy func f1 f2)+    (deleteFirstsBy func (LL.toList f1) (LL.toList f2))+prop_unionBy f1 f2 func = llcmp (LL.unionBy func f1 f2)+    (unionBy func (LL.toList f1) (LL.toList f2))+prop_intersectBy f1 f2 func = llcmp (LL.intersectBy func f1 f2)+    (intersectBy func (LL.toList f1) (LL.toList f2))+prop_groupBy f func =+    (map LL.toList (LL.groupBy func f)) @?= (groupBy func (LL.toList f))+prop_sortBy1 f = llcmp (LL.sortBy compare f) (sortBy compare (LL.toList f))+prop_sortBy2 f = llcmp (LL.sortBy func f) (sortBy func (LL.toList f))+    where func x y = compare y x+prop_sortBy f func = llcmp (LL.sortBy func f) (sortBy func (LL.toList f))+prop_insertBy1 f i = llcmp (LL.insertBy compare i f)+    (insertBy compare i (LL.toList f))+prop_insertBy2 f i = llcmp (LL.insertBy func i f)+    (insertBy func i (LL.toList f))+    where func x y = compare y x+prop_genericLength f =+    LL.genericLength f @?= genericLength (LL.toList f)+prop_genericTake f (i::Integer) = (i >= 0) ==>+    llcmp (LL.genericTake i f) (genericTake i (LL.toList f))+prop_genericDrop f (i::Integer) = (i >= 0) ==>+    llcmp (LL.genericDrop i f) (genericDrop i (LL.toList f))+prop_genericSplitAt f (i::Integer) = i >= 0 ==>+    llcmp [(\(x, y) -> (LL.toList x, LL.toList y)) . LL.genericSplitAt i $ f]+          [LL.genericSplitAt i (LL.toList f)]+prop_genericReplicate f (count::Integer) i = count >= 0 ==>+    llcmp res (genericReplicate count i)+    where res = asTypeOf (LL.genericReplicate count i) f++--prop_zip :: (LL.ListLike full item, LL.ListLike result (item, Int)) =>+--    full -> Result+prop_zip f = LL.zip f f2 @?= zip (LL.toList f) f2+    where f2 = [(-5::Int)..]+prop_zipWith f = +    LL.toList res @?= (zipWith func (LL.toList f) f2)+    where f2 = [(100::Int)..(-100)]+          func x y = (y + 5, x)+          res = asTypeOf (LL.zipWith func f f2) [(5::Int, LL.head f)]+--FIXME: prop_unzip +--FIXME: prop_and+--FIXME: prop_or+--FIXME: prop_sum+--FIXME: prop_product+prop_foldl f func (i::Int) = LL.foldl func i f @?= foldl func i (LL.toList f)+prop_foldl' f func (i::Integer) =+    LL.foldl' func i f @?= foldl' func i (LL.toList f)+prop_foldl1 f func = not (LL.null f) ==> +    (LL.foldl1 func f) @?= (foldl1 func (LL.toList f))+prop_foldr f func (i::Int) = LL.foldr func i f @?= foldr func i (LL.toList f)+prop_foldr' f func (i::Integer) =+    LL.foldr' func i f @?= foldr' func i (LL.toList f)+prop_foldr1 f func = not (LL.null f) ==>+    LL.foldl1 func f @?= foldl1 func (LL.toList f)+prop_fold f = llcmp res resl+    where res = LL.fold f+          resl = fold (map LL.toList (LL.toList f))+prop_foldMap :: (LL.ListLike full item, Eq full) => full -> (item -> [Int]) -> Result+prop_foldMap f func = res @?= resl+    where res = LL.foldMap func f+          resl = foldMap func  (LL.toList f) -- asTypeOf (foldMap (LL.toList f)) (head f)++prop_toString f =+    ((LL.fromString . LL.toString $ f) == f)+    where l = LL.toList f+prop_fromString f x = +    LL.toString (asTypeOf (LL.fromString x) f) @?= x+prop_lines f = map LL.toString res @?= lines (LL.toString f)+    where res = asTypeOf (LL.lines f) [f]+prop_words f = map LL.toString res @?= words (LL.toString f)+    where res = asTypeOf (LL.words f) [f]++allt = [apf "empty" (t prop_empty),+        apf "length" (t prop_length),+        apf "to/fromList" (t prop_tofromlist),+        apf "singleton" (t prop_singleton),+        apf "cons" (t prop_cons),+        apf "append" (t prop_append),+        apf "head" (t prop_head),+        apf "last" (t prop_last),+        apf "tail" (t prop_tail),+        apf "init" (t prop_init),+        apf "null" (t prop_null),+        apf "length2" (t prop_length2),+        apf "length3" (t prop_length3),+        apf "map" (t prop_map),+        apf "rigidMap" (t prop_rigidMap),+        apf "reverse" (t prop_reverse),+        apf "intersperse" (t prop_intersperse),+        apw "concat" (LLWrap prop_concat),+        apf "concatMap" (t prop_concatmap),+        apf "rigidConcatMap" (t prop_rigidConcatMap),+        apf "any" (t prop_any),+        apf "all" (t prop_all),+        apf "maximum" (t prop_maximum),+        apf "minimum" (t prop_minimum),+        apf "replicate" (t prop_replicate),+        apf "take" (t prop_take),+        apf "drop" (t prop_drop),+        apf "splitAt" (t prop_splitAt),+        apf "takeWhile" (t prop_takeWhile),+        apf "dropWhile" (t prop_dropWhile),+        apf "span" (t prop_span),+        apf "break" (t prop_break),+        apf "group" (t prop_group),+        apf "inits" (t prop_inits),+        apf "tails" (t prop_tails),+        apf "isPrefixOf" (t prop_isPrefixOf),+        apf "isSuffixOf" (t prop_isSuffixOf),+        apf "isInfixOf" (t prop_isInfixOf),+        apf "elem" (t prop_elem),+        apf "notElem" (t prop_notElem),+        apf "find" (t prop_find),+        apf "filter" (t prop_filter),+        apf "partition" (t prop_partition),+        apf "index" (t prop_index),+        apf "elemIndex" (t prop_elemIndex),+        apf "elemIndices" (t prop_elemIndices),+        apf "findIndex" (t prop_findIndex),+        apf "findIndices" (t prop_findIndices),+        apf "sequence" (t prop_sequence),+        apf "mapM" (t prop_mapM),+        apf "rigidMapM" (t prop_rigidMapM),+        -- FIXME: mapM_ ?+        apf "nub" (t prop_nub),+        apf "delete" (t prop_delete),+        apf "deleteFirsts" (t prop_deleteFirsts),+        apf "union" (t prop_union),+        apf "intersect" (t prop_intersect),+        apf "sort" (t prop_sort),+        apf "insert" (t prop_insert),+        -- toList+        -- fromList+        -- fromListLike+        apf "nubBy" (t prop_nubBy),+        apf "deleteBy" (t prop_deleteBy),+        apf "deleteFirstsBy" (t prop_deleteFirstsBy),+        apf "unionBy" (t prop_unionBy),+        apf "intersectBy" (t prop_intersectBy),+        apf "groupBy" (t prop_groupBy),+        apf "sortBy1" (t prop_sortBy1),+        apf "sortBy2" (t prop_sortBy2),+        apf "insertBy1" (t prop_insertBy1),+        apf "insertBy2" (t prop_insertBy2),+        apf "genericLength" (t prop_genericLength),+        apf "genericTake" (t prop_genericTake),+        apf "genericDrop" (t prop_genericDrop),+        apf "genericSplitAt" (t prop_genericSplitAt),+        apf "genericReplicate" (t prop_genericReplicate),+        apf "zip" (t prop_zip),+        apf "zipWith" (t prop_zipWith) +        -- apf "unzip" (t prop_unzip),+        -- apf "and" (t prop_and),+        -- apf "or" (t prop_or),+        -- apf "sum" (t prop_sum),+        -- apf "propduct" (t prop_product),+        -- sequence_ +        ]++allf = (if compilerName == "hugs" then [] else [ apf "foldl" (t prop_foldl),+                                                 apf "foldr1" (t prop_foldr1),+                                                 apf "foldl1" (t prop_foldl1)])+       +++       [+        apf "foldl'" (t prop_foldl'),+        apf "foldr" (t prop_foldr),+        apf "foldr'" (t prop_foldr'),+        apw "fold" (LLWrap prop_fold),+        apf "foldMap" (t prop_foldMap) +       ]++alls = [+        aps "toString" (t prop_toString),+        aps "fromString" (t prop_fromString),+        aps "lines" (t prop_lines),+        aps "words" (t prop_words) +        -- FIXME: aps (t prop_unlines),+        -- FIXME: aps (t prop_unwords)+       ]+allTests = HU.TestList $ reverse $+                       [HU.TestLabel "ListLike" (HU.TestList allt),+                        HU.TestLabel "FoldableLL" (HU.TestList allf),+                        HU.TestLabel "StringLike" (HU.TestList alls)]++testh = HU.runTestTT $ allTests+testv = runVerbTestText (HU.putTextToHandle stderr True) $ allTests+         +main = +    do testv+       return ()