packages feed

EdisonAPI (empty) → 1.2.1

raw patch · 12 files changed

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

Dependencies added: base, haskell98, mtl

Files

@@ -0,0 +1,23 @@+Copyright (c) 1998-1999 Chris Okasaki+Portions Copyright (c) 2002 Andrew Bromage+Portions Copyright (c) 2006 Robert Dockins+Portions Copyright (c) 2006 David F. Place+Portions Copyright (c) 2006 Ross Paterson and Ralf Hinze++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.
+ EdisonAPI.cabal view
@@ -0,0 +1,31 @@+Name:           EdisonAPI+Version:        1.2.1+License:        OtherLicense+License-File:   COPYRIGHT+Author:         Chris Okasaki+Maintainer:     robdockins AT fastmail DOT fm+Synopsis:       A library of efficient, purely-functional data structures (API)+Category:       Data Structures+Stability:      stable+Description:+   This package provides the typeclasses that form the Edison+   API and other common utility modules.+Hs-Source-Dirs: src+Exposed-modules:+     Data.Edison+     Data.Edison.Prelude+     Data.Edison.Sym+     Data.Edison.Assoc+     Data.Edison.Coll+     Data.Edison.Coll.Utils+     Data.Edison.Seq+     Data.Edison.Seq.ListSeq+Build-Depends:+     base >= 1.0,+     haskell98 >= 1.0,+     mtl >= 1.0+Extensions:+     MultiParamTypeClasses+     FunctionalDependencies+     UndecidableInstances+Ghc-Options: -funbox-strict-fields -fwarn-incomplete-patterns -O2
+ README view
@@ -0,0 +1,206 @@+Edison: A Library of Efficient Data Structures+Version: 1.2.1+Dec 15, 2006+++About Edison+-----------------------++Edison is a library of purely function data structures for Haskell+originally written by Chris Okasaki.  Conceptually, it consists of two+things:+  1) A set of type classes defining data the following data structure+     abstractions: "sequences", "collections" and "associative collections"+  2) Multiple concrete implementations of each of the abstractions.++In theory, either component may be used independently of the other.++This release is an update to (hopefully) make Edison easier to use,+mostly by updating Edison to use the most current Haskell tools.+The following major changes have been made since version 1.1, which+was released in 1999.++  * Typeclasses updated to use fundeps (by Andrew Bromage)+  * Implementation of ternary search tries (by Andrew Bromage)+  * Modules renamed to use the hierarchical module extension+  * Documentation haddockized+  * Source moved to a darcs repository+  * Build system cabalized+  * Unit tests integrated into a single driver program which exercises+    all the concrete implementations shipped with Edison+  * Multiple additions to the APIs (mostly the associated collection API)+++Hopefully, these changes will make Edison more accessible than it has+been previously.+++License+-----------------------++Edison is released under an MIT style license.  See the COPYRIGHT+file for details.++++Building Edison+-----------------------++Edison is distributed as a set of related Cabal packages.+The EdisonAPI package contains the main API typeclass definitions.+The EdisonCore package provides the main concrete implementations;+this package depends on the EdisonAPI package.  The Edison-test+package contains the test suite and depends on both packages.++You may either manually invoke cabal for each of the sub-packages+as appropriate, or you may use the included Makefile, which will+build and install the EdisonAPI and EdisonCore packages+automaticly.++If you do not have an executable named 'runhaskell' on your search+path, you will need to edit the Makefile and set the RUNHS variable+appropriately (or run the cabal commands manually).++If you wish to build the API docs, you will first need to+build the relevant package and type the following command in+the package subdirectory:++runhaskell Setup.hs haddock+++A Note about Cabal versions+-----------------------------------++This version of edison builds correctly with Cabal version 1.1.4,+which is shipped with GHC 6.4.2.  To build on earlier versions,+it should suffice to:++s/UndecidableInstances/AllowUndecidableInstances/ +s/Hs-Source-Dirs:/Hs-Source-Dir:/++in the .cabal files.++++Notes on portability+----------------------++Short version:++Edison is expected to work correctly on recent GHC and Hugs (with+extensions enabled).  Other Haskell implementations may also work, but+have not been tested.+++Longer version:++Edison uses a number of extensions beyond Haskell 98, the current+official Haskell standard.  These include:++  * Multi-parameter typeclasses+  * Functional dependencies+  * Undecidable instances++In all cases, these extensions are used to allow the typeclass+abstractions to be expressed.  These extensions are fairly popular+and seem likely to make it in some form into a Haskell standard+(hopefully in the not too distant future).++Currently, Edison builds and runs correctly under GHC and Hugs.+More specificly, most development and testing has been done with+GHC 6.4.1, and the test suite builds and runs to completion with no errors.+With Hugs (March 2005 release) and the '-98' option, all of the core Edison+data structures should work correctly.  Unfortunately, the test suite will+not load, due to differences in Hugs' and GHC's implementations of +multi-parameter typeclasses.++As the extensions used are not recent developments, I also expect that less+recent versions of GHC and Hugs will also work.  Other implementations+may also work correctly with Edison, but this has not been tested.++++The Story on Edison Packages+----------------------------------++Cabal is a nice tool for building and distributing Haskell projects.  However,+it has the slightly undesirable property that the "Package" unit is the atomic+unit of compilation, documentation and of dependency resolution.  In order to+support implementations which have varying external dependencies, Edison has been+split into multiple cabal sub-packages, which cooperate.  The root package is+named 'EdisonAPI' and it contains the typeclass specifications, together with+extensive documentation and a few utility classes.  'EdisonAPI' essentially+represents a design contract.  The 'EdisonCore' package contains core Edison+implementations.  These implementations have no dependencies beyond the standard+libraries.  Other implementation modules are planned: these other modules+may have dependencies on eg, Adiran Hay's AVL tree implementation or Don+Stewart's Fast Packed String, etc.  Additionally there is a unit test package.+Currently it is tied to the 'EdisonCore' package, but in the future it will+provide basic unit testing capabilities for extended implementations as well.+++++Edison Versioning+-----------------------++As the maintainer of Edison, I take API stability very seriously.  My goal is+that programs written against Edison will not suffer from version drift.+However, I also wish to allow Edison to incorporate new ideas and evolve into a+better way to use data structures in Haskell.  In order to help accommodate these+somewhat opposing goals, I have adopted the following versioning scheme.  Respect+the versioning scheme, and you should have no compatibility problems.+++Each Edison release number is composed of four components:++  xxx.yyy.zzz.www+   ^   ^   ^   ^+   |   |   |   |+   |   |   |   +------ patch level+   |   |   +---------- API version number+   |   +-------------- minor version number+   +------------------ major version number+++The API version number and/or patch level may be omitted for brevity.  When+omitted, they are assumed to be 0.++I have adopted the (pre-2.6) Linux kernel versioning scheme for major and+minor numbers: the major number is incremented at major updates (ie, something+on the order of total API re-engineering or complete rewrites).  Minor numbers+represent "branches" of development.++Releases with even minor numbers are "stable" releases (0 is considered even).+For example, the Edison 1.2 release is a stable release. Even numbered releases+will have stable user-visible APIs; my goal is that any program compiled against+an Edison stable release will work correctly for all later Edison releases with+the same major and minor version numbers.  This means that API changes will be+limited to additions.  However, I intend that even additions be rare, and they will+only be considered with compelling evidence that the lack of the feature in question+inhibits desirable use cases.  The user-visible behavior of an implementation will+only be changed if it was originally in violation of the contract (ie, a bug).++*NOTE*+THE EXACT BEHAVIOR OF AMBIGUOUS OPERATIONS IS NOT CONSIDERED USER-VISIBLE BEHAVIOR,+nor is the behavior of unsafe operations when used in violation of their preconditions.+Ambiguous operations may change their behavior in stable releases as long as such+changes still obey the design contract.+++Releases with odd minor numbers are "development" branches.  Such releases+are branched from the immediately preceding stable release minor number.+For example, the Edison 1.3 development branch will be forked from the Edison 1.2+release family.  No guarantees are made about the user-visible APIs for development+branches.  API operations may be added, deleted, or have the terms of their design+contracts altered in development branches, and implementations may freely change their+behavior.  Eventually development branches are stabilized and transform into the next+even-numbered stable release.++For both even and odd minor numbers, the third component represents the "API version".+Any change to the API will cause a bump in the API version number.  For stable branches,+this should be fairly rare; for odd branches, it may occur rather frequently.++The fourth component is incremented for each official release whenever the first three+components are not altered.  Two Edison versions which differ only in their patch level+should have identical APIs.
+ Setup.hs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+import Distribution.Simple+main = defaultMainWithHooks defaultUserHooks
+ src/Data/Edison.hs view
@@ -0,0 +1,353 @@+-- |+--   Module      :  Data.Edison+--   Copyright   :  Copyright (c) 2006 Robert Dockins+--   License     :  MIT; see COPYRIGHT file for terms and conditions+--+--   Maintainer  :  robdockins AT fastmail DOT fm+--   Stability   :  stable+--   Portability :  GHC, Hugs (MPTC and FD)+--+--   Edison is a library of purely functional data structures written by+--   Chris Okasaki.  It is named after Thomas Alva Edison and for the+--   mnemonic value /ED/i/S/on (/E/fficent /D/ata /S/tructures).+--+--   Edison provides several families of abstractions, each with+--   multiple implementations.  The main abstractions provided by Edison are:+--+--   * /Sequences/ such as stacks, queues, and dequeues,+--+--   * /Collections/ such as sets, bags and heaps, and+--+--   * /Associative Collections/ such as finite maps and priority queues+--     where the priority and element are distinct.+--+--+--+--   /Conventions:/+--+--   Each data structure is implemented as a separate module.  These modules+--   should always be imported @qualified@ to prevent a flood of name clashes,+--   and it is recommended to rename the module using the @as@ keyword to reduce+--   the overhead of qualified names and to make substituting one implementation+--   for another as painless as possible.+--+--   Names have been chosen to match standard usage as much as possible.  This+--   means that operations for abstractions frequently share the same name+--   (for example, @empty@, @null@, @size@, etc).  It also means that in many+--   cases names have been reused from the Prelude.  However, the use of+--   @qualified@ imports will prevent name reuse from becoming name clashes.  If+--   for some reason you chose to import an Edison data structure unqualified,+--   you will likely need to import the Prelude @hiding@ the relevant names.+--+--   Edison modules also frequently share type names.  For example, most sequence+--   type constructors are named @Seq@.  This additionally aids substituting+--   implementations by simply importing a different module.+--+--   Argument orders are selected with the following points in mind:+--+--   * /Partial application:/ arguments more likely to be static usually+--     appear before other arguments in order to facilitate partial+--     application.+--+--   * /Collection appears last:/ in all cases where an operation queries a+--     single collection or modifies an existing collection, the collection+--     argument will appear last.  This is something of a de facto standard+--     for Haskell datastructure libraries+--     and lends a degree of consistency to the API.+--+--   * /Most usual order:/ where an operation represents a well-known+--     mathematical function on more than one datastructure, the arguments+--     are chosen to match the most usual argument order for the function.+--+--+--   /Type classes:/+--+--   Each family of abstractions is defined as a set of classes: a main class+--   that every implementation of that abstraction should support and several+--   auxiliary subclasses that an implementation may or may not support. However,+--   not all applications require the power of type classes, so each method+--   is also directly accessible from the implementation module.  Thus you can+--   choose to use overloading or not, as appropriate for your particular+--   application.+--+--   Documentation about the behavior of data structure operations is defined+--   in the modules "Data.Edison.Seq", "Data.Edison.Coll" and+--   "Data.Edison.Assoc".  Implementations are required to respect+--   the descriptions and axioms found in these modules.  In some cases time+--   complexity is also given.  Implementations may differ from these time+--   complexities; if so, the differences will be given in the documentation for+--   the individual implementation module.+--+--+--+--   /Notes on Eq and Ord instances:/+--+--   Many Edison data structures require @Eq@ or @Ord@ contexts to define equivalence+--   and total ordering on elements or keys.  Edison makes the following assumptions+--   about all such required instances:+--+--   * An @Eq@ instance correctly defines an equivalence relation (but not necessarily+--     structural equality); that is, we assume @(==)@ (considered as a+--     relation) is reflexive, symmetric and transitive, but allow that equivalent+--     items may be distinguishable by other means.+--+--   * An @Ord@ instance correctly defines a total order which is consistent with+--     the @Eq@ instance for that type.+--+--   These assumptions correspond to the usual meanings assigned to these classes.  If+--   an Edison data structure is used with an @Eq@ or @Ord@ instance which violates these+--   assumptions, then the behavior of that data structure is undefined.+--+--+--+--   /Notes on Read and Show instances:/+--+--   The usual Haskell convention for @Read@ and @Show@ instances (as championed by the+--   Haskell \"deriving\" mechanism), is that @show@ generates a string which is a+--   valid Haskell expression built up+--   using the data type's data constructors such that, if interpreted as Haskell code, the+--   string would generate an identical data item.  Furthermore, the derived  @Read@+--   instances are able to parse such strings, such that @(read . show) === id@.+--   So, derived instances of @Read@ and @Show@ exhibit+--   the following useful properties:+--+--   * @read@ and @show@ are complementary; that is, @read@ is a useful inverse for @show@+--+--   * @show@ generates a string which is legal Haskell code representing the data item+--+--   For concrete data types, the deriving mechanism is usually quite sufficient.+--   However, for abstract types the derived @Read@ instance may allow users to create data+--   which violates invariants. Furthermore, the strings resulting from @show@ reference hidden+--   data constructors which violates good software engineering principles and also+--   cannot be compiled because the constructors are not available outside the defining module.+--+--   Edison avoids most of these problems and still maintains the above useful properties by+--   doing conversions to and from lists and inserting explicit calls to the list conversion+--   operations.  The corresponding @Read@ instance strips the list conversion call before+--   parsing the list.  In this way, private data constructors are not revealed and @show@ strings+--   are still legal, compilable Haskell code.  Furthermore, the showed strings gain a degree of+--   independence from the underlying datastructure implementation.+--+--   For example, calling @show@ on an empty Banker's queue will result in the following string:+--+-- > Data.Edison.Seq.BankersQueue.fromList []+--+--   Datatypes which are not native Edison data structures (such as StandardSet and StandardMap)+--   may or may not provide @Read@ or @Show@ instances and, if they exist, they may or may+--   not also provide the properties that Edison native @Read@ and @Show@ instances do.+--+--+--   /Notes on time complexities:/+--+--   Some Edison data structures (only the sequences currently) have detailed time complexity+--   information.  Unless otherwise stated, these are amortized time complexities, assuming+--   persistent usage of the datastructure.  Much of this data comes from:+--+--   Martin Holters. /Efficent Data Structures in a Lazy Functional Language/.  Master's Thesis.+--   Chalmers University of Technology, Sweden. 2003.+--+--   /Notes on unsafe functions:/+--+--   There are a number of different notions of what constitutes an unsafe function.+--   In Haskell, a function is generally called \"unsafe\" if it can subvert+--   type safety or referential integrity, such as @unsafePerformIO@ or @unsafeCoerce#@.+--   In Edison, however, we downgrade the meaning of \"unsafe\" somewhat.  An+--   \"unsafe\" Edison function is one which, if misused, can violate the structural+--   invariants of a data structure.  Misusing an Edison \"unsafe\" function should+--   never cause your runtime to crash or break referential integrity, but it may cause+--   later uses of a data structure to behave in undefined ways.  Almost all unsafe functions+--   in Edison are labeled with the @unsafe@ prefix.  An exception to this rule is the+--   @With@ functions in the 'Set' class, which are also unsafe but do not have+--   the prefix.  Unsafe functions will have explicit preconditions listed in their+--   documentation.+--+--+--+--   /Notes on ambiguous functions:/+--+--   Edison also contains some functions which are labeled \"ambiguous\".  These+--   functions cannot violate the structural invariants of a data structure, but, under+--   some conditions, the result of applying an ambiguous function is not well defined.+--   For ambiguous functions, the result of applying the function may depend on otherwise+--   unobservable internal state of the data structure, such as the actual shape of a+--   balanced tree.  For example, the 'AssocX' class contains the @fold@ function, which+--   folds over the elements in the collection in an arbitrary order.  If the combining+--   function passed to @fold@ is not fold-commutative (see below), then the result of+--   the fold will depend on the actual order that elements are presented to the+--   combining function, which is not defined.+--+--   To aid programmers, each API function is labeled /ambiguous/ or /unambiguous/ in its+--   documentation.  If a function is unambiguous only under some circumstances,+--   that will also be explicitly stated.+--+--   An \"unambiguous\" operation is one where all correct implementations of the operation+--   will return \"indistinguishable\" results.  For concrete data types, \"indistinguishable\"+--   means structural equality.  An instance of an abstract data type is considered+--   indistinguishable from another if all possible applications of unambiguous+--   operations to both yield indistinguishable results.  (Note: this definition is+--   impredicative and rather imprecise.  Should it become an issue, I will attempt to+--   develop a better definition.  I hope the intent is sufficiently clear).+--+--   A higher-order unambiguous operation may be rendered ambiguous if passed a \"function\" which+--   does not respect referential integrity (one containing @unsafePerformIO@ for example).+--   Only do something like this if you are 110% sure you know what you are doing, and even then+--   think it over two or three times.+--+--+--+--   /How to choose a fold:/+--+--   /Folds/ are an important class of operations on data structures in a functional+--   language; they perform essentially the same role that iterators perform in+--   imperative languages.  Edison provides a dizzying array of folds which (hopefully)+--   correspond to all the various ways a programmer might want to fold over a data+--   structure.  However, it can be difficult to know which fold to choose for a+--   particular application.  In general, you should choose a fold which provides+--   the /fewest/ guarantees necessary for correctness.  The folds which have fewer+--   guarantees give data structure implementers more leeway to provide efficient+--   implementations.  For example, if you which to fold a commutative, associative+--   function, you should chose @fold@ (which does not guarantee an order) over @foldl@+--   or @foldr@, which specify particular orders.+--+--   Also, if your function is strict in+--   the accumulating argument, you should prefer the strict folds (eg, @fold'@); they will+--   often provide better space behavior.  /Be aware/, however, that the \"strict\" folds+--   are not /necessarily/ more strict than the \"non-strict\" folds; they merely give+--   implementers the option to provide additional strictness if it improves performance.+--+--   For associative collections, only use with @WithKey@ folds if you actually need the+--   value of the key.+--+--+--   /Painfully detailed information about ambiguous folds:/+--+--   All of the folds that are listed ambiguous are ambiguous because they do not or cannot+--   guarantee a stable order with which the folding function will be applied.  However,+--   some functions are order insensitive, and the result will be unambiguous regardless+--   of the fold order chosen.  Here we formalize this property, which we call+--   \"fold commutativity\".+--+--   We say @f :: a -> b -> b@ is /fold-commutative/ iff @f@ is unambiguous and+--+-- >    forall w, z :: b; m, n :: a+-- >+-- >       w = z ==> f m (f n w) = f n (f m z)+-- >+--+--   where @=@ means indistinguishability.+--+--   This property is sufficient (but not necessary) to ensure that, for any+--   collection of elements to+--   fold over, folds over all permutations of those elements will generate+--   indistinguishable results.  In other words, an ambiguous fold applied to a+--   fold-commutative combining function becomes /unambiguous/.+--+--   Some fold combining functions take their arguments in the reverse order.  We+--   straightforwardly extend the notion of fold commutativity to such functions+--   by reversing the arguments.  More formally, we say @g :: b -> a -> b@ is fold+--   commutative iff @flip g :: a -> b -> b@ is fold commutative.+--+--   For folds which take both a key and an element value, we extend the notion of fold+--   commutativity by considering the key and element to be a single, uncurried argument.+--   More formally, we say @g :: k -> a -> b -> b@ is fold commutative iff+--+-- >    \(k,x) z -> g k x z :: (k,a) -> b -> b+--+--   is fold commutative according to the above definition.+--+--   Note that for @g :: a -> a -> a@, if @g@ is unambiguous,+--   commutative, and associative, then @g@ is fold-commutative.+--+--   Proof:+--+-- >    let w = z, then+-- >    g m (g n w) = g m (g n z)     g is unambiguous+-- >                = g (g n z) m     commutative property of g+-- >                = g n (g z m)     associative property of g+-- >                = g n (g m z)     commutative property of g+--+--   Qed.+--+--   Thus, many common numeric combining functions, including @(+)@ and @(*)@ at+--   integral types, are fold commutative and can be safely used with ambiguous+--   folds.+--+--   /Be aware/ however, that @(+)@ and @(*)@ at floating point types are only+--   /approximately/ commutative and associative due to rounding errors; using+--   ambiguous folds with these operations may result in subtle differences in+--   the results.  As always, be aware of the limitations and numeric+--   properties of floating point representations.+--+--+--+--   /About this module:/+--+--   This module re-exports the various data structure abstraction classes, but+--   not their methods. This allows you to write type signatures which have+--   contexts that mention Edison type classes without having to import the+--   appropriate modules @qualified@.  The class methods are not exported to+--   avoid name clashes.  Obviously, to use the methods of these classes, you+--   will have to import the appropriate modules.  This module additionally+--   re-exports the entire "Data.Edison.Prelude" module.+--+--+--+--   /Miscellaneous points:/+--+--   Some implementations export a few extra functions beyond those included+--   in the relevant classes.  These are typically operations that are+--   particularly efficient for that implementation, but are not general enough+--   to warrant inclusion in a class.+--+--   Since qualified infix symbols are fairly ugly, they have been largely avoided.+--   However, the "Data.Edison.Sym" module defines a number of infix operators+--   which alias the prefix operators; this module is intended to be imported+--   unqualified.+--+--   Most of the operations on most of the data structures are strict.  This is+--   inevitable for data structures with non-trivial invariants. Even given+--   that, however, many of the operations are stricter than necessary.  In+--   fact, operations are never deliberately made lazy unless the laziness is+--   required by the algorithm, as can happen with amortized data structures.+--+--   Note, however, that the various sequence implementations are always lazy+--   in their elements.  Similarly, associative collections are always lazy in+--   their elements (but usually strict in their keys).  Non-associative+--   collections are usually strict in their elements.++module Data.Edison (++-- * Sequence class+  Sequence++-- * Collection classes+-- ** Non-observable collections+, CollX+, OrdCollX+, SetX+, OrdSetX+-- ** Observable collections+, Coll+, OrdColl+, Set+, OrdSet++-- * Associative collection classes+-- ** Non-observable associative collections+, AssocX+, OrdAssocX+, FiniteMapX+, OrdFiniteMapX+-- ** Observable associative collections+, Assoc+, OrdAssoc+, FiniteMap+, OrdFiniteMap++, module Data.Edison.Prelude+) where++import Data.Edison.Prelude+import Data.Edison.Seq+import Data.Edison.Coll+import Data.Edison.Assoc
+ src/Data/Edison/Assoc.hs view
@@ -0,0 +1,931 @@+-- |+--   Module      :  Data.Edison.Assoc+--   Copyright   :  Copyright (c) 1998 Chris Okasaki+--   License     :  MIT; see COPYRIGHT file for terms and conditions+--+--   Maintainer  :  robdockins AT fastmail DOT fm+--   Stability   :  stable+--   Portability :  GHC, Hugs (MPTC and FD)+--+--   The /associative collection/ abstraction includes finite maps, finite+--   relations, and priority queues where the priority is separate from the+--   element.  Associative collections are defined in Edison as a set of eight+--   classes.+--+--   Note that this+--   hierarchy mirrors the hierarchy for collections, but with the addition+--   of 'Functor' as a superclass of every associative collection. See +--   "Data.Edison.Coll" for a description of the class hierarchy.+--+--   In almost all cases, associative collections make no guarantees about+--   behavior with respect to the actual keys stored and (in the case of+--   observable maps) which keys can be retrieved.  We adopt the convention+--   that methods which create associative collections are /unambiguous/+--   with respect to the key storage behavior, but that methods which can+--   observe keys are /ambiguous/ with respect to the actual keys returned.+--+--   In all cases where an operation is ambiguous with respect to the key,+--   the operation is rendered /unambiguous/ if the @Eq@ instance on keys+--   corresponds to indistinguisability.++module Data.Edison.Assoc (+    -- * Superclass aliases+    map,++    -- * Non-observable associative collections+    AssocX(..),+    OrdAssocX(..),+    FiniteMapX(..),+    OrdFiniteMapX,++    -- * Observable associative collections+    Assoc(..),+    OrdAssoc(..),+    FiniteMap(..),+    OrdFiniteMap,++    -- * Specilizations of submap operations+    submap,+    properSubmap,+    sameMap,++    -- * Specializations of sequence operations to lists+    fromList,+    insertList,+    unionList,+    deleteList,+    lookupList,+    elementsList,+    unsafeFromOrdList,+    fromListWith,+    fromListWithKey,+    insertListWith,+    insertListWithKey,+    unionListWith,+    toList,+    keysList,+    toOrdList,+    unionListWithKey++) where++import Prelude hiding (null,map,lookup,foldr,foldl,foldr1,foldl1,filter)++import Data.Edison.Prelude++import Data.Edison.Seq(Sequence)+import Data.Edison.Seq.ListSeq()+++-- | Apply a function to the elements of every binding in the associative+--   collection.  Identical to @fmap@ from @Functor@.+--+--   This function is always /unambiguous/.+map :: AssocX m k => (a -> b) -> m a -> m b+map = fmap++-- | Specialization of 'submapBy' where the comparison function is+--   given by @(==)@.+submap :: (Eq a,FiniteMapX m k) => m a -> m a -> Bool+submap = submapBy (==)++-- | Specialization of 'properSubmapBy' where the comparison function+--   is given by @(==)@.+properSubmap :: (Eq a, FiniteMapX m k) => m a -> m a -> Bool+properSubmap = properSubmapBy (==)++-- | Specialization of 'sameMapBy' where the comparison function is+--   given by @(==)@.+sameMap :: (Eq a,FiniteMapX m k) => m a -> m a -> Bool+sameMap = sameMapBy (==)+++-- | The root class of the associative collection hierarchy.+class (Eq k,Functor m) => AssocX m k | m -> k where++  -- | The empty associative collection.+  --+  --   This function is always /unambiguous/.+  empty          :: m a++  -- | Create an associative collection with a single binding.+  --+  --   This function is always /unambiguous/.+  singleton      :: k -> a -> m a++  -- | Create an associative collection from a  list of bindings. Which element+  --   and key are kept in the case of duplicate keys is unspecified.+  --+  --   This function is /ambiguous/ at finite map types if the sequence+  --   contains more than one equivalent key.  Otherwise it is /unambiguous/.+  fromSeq        :: Sequence seq => seq (k,a) -> m a++  -- | Add a binding to an associative collection.  For finite maps, 'insert'+  --   keeps the new element in the case of duplicate keys.+  --+  --   This function is /unambiguous/.+  insert         :: k -> a -> m a -> m a++  -- | Add a sequence of bindings to a collection.  For finite maps, which key+  --   and which element are kept in the case of duplicates is unspecified.+  --   However, if a key appears in the sequence and in the map, (one of) the+  --   elements in the list will be given preference.+  --+  --   This function is /ambiguous/ at finite map types if the sequence contains+  --   more than one equivalent key.  Otherwise it is /unambiguous/.+  insertSeq      :: Sequence seq => seq (k,a) -> m a -> m a++  -- | Merge two associative collections.  For finite maps, which element+  --   to keep in the case of duplicate keys is unspecified.+  --+  --   This function is /ambiguous/ at finite map types if the map keys are not+  --   disjoint.  Otherwise it is /unambiguous/.+  union          :: m a -> m a -> m a++  -- | Merge a sequence of associative collections.  Which element+  --   to keep in the case of duplicate keys is unspecified.+  --+  --   This function is /ambiguous/ at finite map types if the map keys are not+  --   mutually disjoint.  Otherwise it is /unambiguous/.+  unionSeq       :: Sequence seq => seq (m a) -> m a++  -- | Delete one binding with the given key, or leave the associative collection+  --   unchanged if it does not contain the key.  For bag-like associative+  --   collections, it is unspecified which binding will be removed.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears more+  --   than once in the relation.  Otherwise it is /unambiguous/.+  delete         :: k -> m a -> m a++  -- | Delete all bindings with the given key, or leave the associative collection+  --   unchanged if it does not contain the key.+  --+  --   This function is always /unambiguous/.+  deleteAll      :: k -> m a -> m a++  -- | Delete a single occurrence of each of the given keys from an associative+  --   collection.  For bag-like associative collections containing duplicate keys,+  --   it is unspecified which bindings will be removed.+  --+  --   This function is /ambiguous/ at finite relation types if any key appears both+  --   in the sequence and in the finite relation AND the number of occurrences in+  --   the sequence is less than the number of occurrences in the finite relation.+  --   Otherwise it is /unambiguous/.+  deleteSeq      :: Sequence seq => seq k -> m a -> m a++  -- | Test whether the associative collection is empty.+  --+  --   /Axioms:/+  --+  -- * @null m = (size m == 0)@+  --+  --   This function is always /unambiguous/.+  null           :: m a -> Bool++  -- | Return the number of bindings in the associative collection.+  --+  --   This function is always /unambiguous/.+  size           :: m a -> Int++  -- | Test whether the given key is bound in the associative collection.+  --+  --   This function is always /unambiguous/.+  member         :: k -> m a -> Bool++  -- | Returns the number of bindings with the given key.  For finite maps+  --   this will always return 0 or 1.+  --+  --   This function is always /unambiguous/.+  count          :: k -> m a -> Int++  -- | Find the element associated with the given key.  Signals an error if+  --   the given key is not bound.  If more than one element is bound by the+  --   given key, it is unspecified which is returned.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears+  --   more than once in the finite relation.  Otherwise, it is /unambiguous/.+  lookup         :: k -> m a -> a++  -- | Find the element associated with the given key.  Calls 'fail' if the+  --   given key is not bound.  If more than one element is bound by the given+  --   key, it is unspecified which is returned.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears+  --   more than once in the finite relation.  Otherwise, it is /unambiguous/.+  lookupM        :: (Monad rm) => k -> m a -> rm a++  -- | Return all elements bound by the given key in an unspecified order.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears+  --   more than once in the finite relation.  Otherwise, it is /unambiguous/.+  lookupAll      :: Sequence seq => k -> m a -> seq a++  -- | Find the element associated with the given key; return the element+  --   and the collection with that element deleted.  Signals an error if+  --   the given key is not bound.  If more than one element is bound by the+  --   given key, it is unspecified which is deleted and returned.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears+  --   more than once in the finite relation.  Otherwise, it is /unambiguous/.+  lookupAndDelete :: k -> m a -> (a, m a)++  -- | Find the element associated with the given key; return the element+  --   and the collection with that element deleted.  Calls @fail@ if+  --   the given key is not bound.  If more than one element is bound by the+  --   given key, it is unspecified which is deleted and returned.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears+  --   more than once in the finite relation.  Otherwise, it is /unambiguous/.+  lookupAndDeleteM :: (Monad rm) => k -> m a -> rm (a, m a)++  -- | Find all elements bound by the given key; return a sequence containing+  --   all such bound elements in an unspecified order and the collection+  --   with all such elements deleted.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears+  --   more than once in the finite relation.  Otherwise, it is /unambiguous/.+  lookupAndDeleteAll :: (Sequence seq) => k -> m a -> (seq a,m a)++  -- | Return the element associated with the given key.  If no such element+  --   is found, return the default.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears+  --   more than once in the finite relation.  Otherwise, it is /unambiguous/.+  lookupWithDefault  :: a    -- ^ default element+                     -> k    -- ^ the key to look up+                     -> m a  -- ^ the associative collection+                     -> a++  -- | Change a single binding for the given key by applying a function to its+  --   element.  If the key binds more than one element, it is unspecified which+  --   will be modified.  If the key is not found in the collection, it is returned+  --   unchanged.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears+  --   more than once in the finite relation.  Otherwise, it is /unambiguous/.+  adjust         :: (a -> a) -> k -> m a -> m a++  -- | Change all bindings for the given key by applying a function to its+  --   elements.  If the key is not found in the collection, it is returned+  --   unchanged.+  --+  --   This function is always /unambiguous/.+  adjustAll      :: (a -> a) -> k -> m a -> m a++  -- | Searches for a matching key in the collection.  If the key is found,+  --   the given function is called to adjust the value.  If the key is not+  --   found, a new binding is inserted with the given element. If the given+  --   key is bound more than once in the collection, it is unspecified+  --   which element is adjusted.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears+  --   more than once in the finite relation.  Otherwise, it is /unambiguous/.+  adjustOrInsert    :: (a -> a) -> a -> k -> m a -> m a++  -- | Searches for all matching keys in the collection.  If the key is found,+  --   the given function is applied to all its elements to adjust their values.+  --   If the key is not found, a new binding is inserted with the given element.+  --+  --   This function is always /unambiguous/.+  adjustAllOrInsert :: (a -> a) -> a -> k -> m a -> m a++  -- | Change or delete a single binding for the given key by applying a function+  --   to its element.  If the function returns @Nothing@, then the binding+  --   will be deleted.  If the key binds more than one element, it is unspecified which+  --   will be modified.  If the key is not found in the collection, it is returned+  --   unchanged.+  --+  --   This function is /ambiguous/ at finite relation types if the key appears+  --   more than once in the finite relation.  Otherwise, it is /unambiguous/.+  adjustOrDelete    :: (a -> Maybe a) -> k -> m a -> m a++  -- | Change or delete all bindings for the given key by applying a function to+  --   its elements.  For any element where the function returns @Nothing@, the+  --   corresponding binding is deleted.  If the key is not found in the collection,+  --   it is returned unchanged.+  --+  --   This function is always /unambiguous/.+  adjustOrDeleteAll :: (a -> Maybe a) -> k -> m a -> m a++  -- | Combine all the elements in the associative collection, given a combining+  --   function and an initial value.  The elements are processed in an+  --   unspecified order.  /Note/ that 'fold' ignores the keys.+  --+  --   @fold f@ is /unambiguous/ iff @f@ is fold-commutative.+  fold           :: (a -> b -> b) -> b -> m a -> b++  -- | A strict variant of 'fold'.+  --+  --   @fold' f@ is /unambiguous/ iff @f@ is fold-commutative.+  fold'          :: (a -> b -> b) -> b -> m a -> b++  -- | Combine all the elements in a non-empty associative collection using the+  --   given combining function.  Signals an error if the associative collection+  --   is empty.  The elements are processed in an unspecified order.  An+  --   implementation may choose to process the elements linearly or in a+  --   balanced fashion (like 'reduce1' on sequences).  /Note/ that 'fold1'+  --   ignores the keys.+  --+  --   @fold1 f@ is /unambiguous/ iff @f@ is fold-commutative.+  fold1          :: (a -> a -> a) -> m a -> a++  -- | A strict variant of 'fold1'.+  --+  --   @fold1' f@ is /unambiguous/ iff @f@ is fold-commutative.+  fold1'         :: (a -> a -> a) -> m a -> a++  -- | Extract all bindings whose elements satisfy the given predicate.+  --+  --   This function is always /unambiguous/.+  filter         :: (a -> Bool) -> m a -> m a++  -- | Split an associative collection into those bindings which satisfy the+  --   given predicate, and those which do not.+  --+  --   This function is always /unambiguous/.+  partition      :: (a -> Bool) -> m a -> (m a, m a)++  -- | Returns all the elements in an associative collection, in an unspecified+  --   order.+  --+  --   This function is /ambiguous/ iff the associative collection contains+  --   more than one element.+  elements       :: Sequence seq => m a -> seq a++  -- | Semanticly, this function is a partial identity function.  If the+  --   datastructure is infinite in size or contains exceptions or non-termination+  --   in the structure itself, then @strict@ will result in bottom.  Operationally,+  --   this function walks the datastructure forcing any closures.  Elements contained+  --   in the map are /not/ forced.+  --+  --   This function is always /unambiguous/.+  strict :: m a -> m a++  -- | Similar to 'strict', this function walks the datastructure forcing closures.+  --   However, @strictWith@ will additionally apply the given function to the+  --   map elements, force the result using @seq@, and then ignore it.+  --   This function can be used to perform various levels of forcing on the+  --   sequence elements.  In particular:+  --+  -- > strictWith id xs+  --+  --   will force the spine of the datastructure and reduce each element to WHNF.+  --+  --   This function is always /unambiguous/.+  strictWith :: (a -> b) -> m a -> m a++  -- | A method to facilitate unit testing.  Returns 'True' if the structural+  --   invariants of the implementation hold for the given associative+  --   collection.  If this function returns 'False', it represents a bug;+  --   generally, either the implementation itself is flawed, or an unsafe+  --   operation has been used while violating the preconditions.+  structuralInvariant :: m a -> Bool++  -- | Returns the name of the module implementing this associative collection.+  instanceName   :: m a -> String+++-- | An associative collection where the keys additionally have an ordering+--   relation.+class (AssocX m k, Ord k) => OrdAssocX m k | m -> k where+  -- | Remove the binding with the minimum key, and return its element together+  --   with the remaining associative collection.  Calls 'fail' if the+  --   associative collection is empty.  Which binding is removed if there+  --   is more than one minimum is unspecified.+  --+  --   This function is /ambiguous/ at finite relation types if the finite relation+  --   contains more than one minimum key.  Otherwise it is /unambiguous/.+  minView            :: (Monad rm) => m a -> rm (a, m a)++  -- | Find the binding with the minimum key and return its element. Signals+  --   an error if the associative collection is empty.  Which element is chosen+  --   if there is more than one minimum is unspecified.+  --+  --   This function is /ambiguous/ at finite relation types if the finite relation+  --   contains more than one minimum key.  Otherwise it is /unambiguous/.+  minElem            :: m a -> a++  -- | Remove the binding with the minimum key and return the remaining+  --   associative collection, or return empty if it is already empty.+  --+  --   This function is /ambiguous/ at finite relation types if the finite relation+  --   contains more than one minimum key.  Otherwise it is /unambiguous/.+  deleteMin          :: m a -> m a++  -- | Insert a binding into an associative collection with the precondition+  --   that the given key is @\<=@ any existing keys already in the collection.+  --   For finite maps, this precondition is strengthened to @\<@.+  --+  --   This function is /unambiguous/ under the preconditions.+  unsafeInsertMin    :: k -> a -> m a -> m a++  -- | Remove the binding with the maximum key, and return its element together+  --   with the remaining associative collection.  Calls 'fail' if the+  --   associative collection is empty.  Which binding is removed if there+  --   is more than one maximum is unspecified.+  --+  --   This function is /ambiguous/ at finite relation types if the finite relation+  --   contains more than one minimum key.  Otherwise it is /unambiguous/.+  maxView            :: (Monad rm) => m a -> rm (a, m a)++  -- | Find the binding with the maximum key and return its element.  Signals+  --   an error if the associative collection is empty.  Which element is chosen+  --   if there is more than one maximum is unspecified.+  --+  --   This function is /ambiguous/ at finite relation types if the finite relation+  --   contains more than one minimum key.  Otherwise it is /unambiguous/.+  maxElem            :: m a -> a++  -- | Remove the binding with the maximum key and return the remaining+  --   associative collection, or return empty if it is already empty.+  --+  --   This function is /ambiguous/ at finite relation types if the finite relation+  --   contains more than one minimum key.  Otherwise it is /unambiguous/.+  deleteMax          :: m a -> m a++  -- | Insert a binding into an associative collection with the precondition+  --   that the given key is @>=@ any existing keys already in the collection.+  --   For finite maps, this precondition is strengthened to @>@.+  --+  --   This function is /unambiguous/ under the precondition.+  unsafeInsertMax    :: k -> a -> m a -> m a++  -- | Fold across the elements of an associative collection in non-decreasing+  --   order by key with right associativity.  For finite maps, the order+  --   is increasing.+  --+  --   @foldr f@ is /unambiguous/ if @f@ is fold-commutative, at finite+  --   map types, or at finite relation types if the relation contains no+  --   duplicate keys.  Otherwise it is /ambiguous/.+  foldr              :: (a -> b -> b) -> b -> m a -> b++  -- | A strict variant of 'foldr'.+  --+  --   @foldr' f@ is /unambiguous/ if @f@ is fold-commutative, at finite+  --   map types, or at finite relation types if the relation contains no+  --   duplicate keys.  Otherwise it is /ambiguous/.+  foldr'             :: (a -> b -> b) -> b -> m a -> b++  -- | Fold across the elements of an associative collection in non-decreasing+  --   order by key with left associativity.  For finite maps, the order+  --   is increasing.+  --+  --   @foldl f@ is /unambiguous/ if @f@ is fold-commutative, at finite+  --   map types, or at finite relation types if the relation contains no+  --   duplicate keys.  Otherwise it is /ambiguous/.+  foldl              :: (b -> a -> b) -> b -> m a -> b++  -- | A strict variant of 'foldl'.+  --+  --   @foldl' f@ is /unambiguous/ if @f@ is fold-commutative, at finite+  --   map types, or at finite relation types if the relation contains no+  --   duplicate keys.  Otherwise it is /ambiguous/.+  foldl'             :: (b -> a -> b) -> b -> m a -> b++  -- | Fold across the elements of an associative collection in non-decreasing+  --   order by key with right associativity.  Signals an error if the+  --   associative collection is empty.  For finite maps, the order is+  --   increasing.+  --+  --   @foldr1 f@ is /unambiguous/ if @f@ is fold-commutative, at finite+  --   map types, or at finite relation types if the relation contains no+  --   duplicate keys.  Otherwise it is /ambiguous/.+  foldr1             :: (a -> a -> a) -> m a -> a++  -- | A strict variant of 'foldr1'.+  --+  --   @foldr1' f@ is /unambiguous/ if @f@ is fold-commutative, at finite+  --   map types, or at finite relation types if the relation contains no+  --   duplicate keys.  Otherwise it is /ambiguous/.+  foldr1'            :: (a -> a -> a) -> m a -> a++  -- | Fold across the elements of an associative collection in non-decreasing+  --   order by key with left associativity.  Signals an error if the+  --   associative collection is empty.  For finite maps, the order is+  --   increasing.+  --+  --   @foldl1 f@ is /unambiguous/ if @f@ is fold-commutative, at finite+  --   map types, or at finite relation types if the relation contains no+  --   duplicate keys.  Otherwise it is /ambiguous/.+  foldl1             :: (a -> a -> a) -> m a -> a++  -- | A strict variant of 'foldl1'.+  --+  --   @foldl1' f@ is /unambiguous/ if @f@ is fold-commutative, at finite+  --   map types, or at finite relation types if the relation contains no+  --   duplicate keys.  Otherwise it is /ambiguous/.+  foldl1'            :: (a -> a -> a) -> m a -> a++  -- | Convert a sequence of bindings into an associative collection with the+  --   precondition that the sequence is sorted into non-decreasing order by+  --   key.  For finite maps, this precondition is strengthened to increasing+  --   order.+  --+  --   This function is /unambiguous/ under the precondition.+  unsafeFromOrdSeq   :: Sequence seq => seq (k,a) -> m a++  -- | Merge two associative collections with the precondition that every key+  --   in the first associative collection is @\<=@ every key in the second+  --   associative collection.  For finite maps, this precondition is+  --   strengthened to @\<@.+  --+  --   This function is /unambiguous/ under the precondition.+  unsafeAppend       :: m a -> m a -> m a++  -- | Extract all bindings whose keys are @\<@ the given key.+  --+  --   This function is always /unambiguous/.+  filterLT           :: k -> m a -> m a++  -- | Extract all bindings whose keys are @\<=@ the given key.+  --+  --   This function is always /unambiguous/.+  filterLE           :: k -> m a -> m a++  -- | Extract all bindings whose keys are @>@ the given key.+  --+  --   This function is always /unambiguous/.+  filterGT           :: k -> m a -> m a++  -- | Extract all bindings whose keys are @>=@ the given key.+  --+  --   This function is always /unambiguous/.+  filterGE           :: k -> m a -> m a++  -- | Split an associative collection into two sub-collections, containing+  --   those bindings whose keys are @\<@ the given key and those which are @>=@.+  --+  --   This function is always /unambiguous/.+  partitionLT_GE     :: k -> m a -> (m a, m a)++  -- | Split an associative collection into two sub-collections, containing+  --   those bindings whose keys are @\<=@ the given key and those which are @>@.+  --+  --   This function is always /unambiguous/.+  partitionLE_GT     :: k -> m a -> (m a, m a)++  -- | Split an associative collection into two sub-collections, containing+  --   those bindings whose keys are @\<@ the given key and those which are @>@.+  --   All bindings with keys equal to the given key are discarded.+  --+  --   This function is always /unambiguous/.+  partitionLT_GT     :: k -> m a -> (m a, m a)++-- | An associative collection where the keys form a set; that is, each key+--   appears in the associative collection at most once.++class AssocX m k => FiniteMapX m k | m -> k where++  -- | Same as 'fromSeq', but with a combining function to resolve duplicates.+  --+  --   This function is always /unambiguous/.+  fromSeqWith        :: Sequence seq => (a -> a -> a) -> seq (k,a) -> m a++  -- | Same as 'fromSeq', but with a combining function to resolve duplicates;+  --   the combining function takes the key in addition to the two elements.+  --+  --   This function is always /unambiguous/.+  fromSeqWithKey     :: Sequence seq => (k -> a -> a -> a) -> seq (k,a) -> m a++  -- | Same as 'insert', but with a combining function to resolve duplicates.+  --+  --   This function is /unambiguous/.+  insertWith         :: (a -> a -> a) -> k -> a -> m a -> m a++  -- | Same as 'insert', but with a combining function to resolve duplicates;+  --   the combining function takes the key in addition to the two elements.+  --   The key passed to the combining function is always the same as the+  --   given key.+  --+  --   This function is /unambiguous/.+  insertWithKey      :: (k -> a -> a -> a) -> k -> a -> m a -> m a++  -- | Same as 'insertSeq', but with a combining function to resolve duplicates.+  --+  --   This function is /unambiguous/.+  insertSeqWith      :: Sequence seq =>+                           (a -> a -> a) -> seq (k,a) -> m a -> m a++  -- | Same as 'insertSeq', but with a combining function to resolve duplicates;+  --   the combining function takes the key in addition to the two elements.+  --+  --   This function is /unambiguous/.+  insertSeqWithKey   :: Sequence seq =>+                           (k -> a -> a -> a) -> seq (k,a) -> m a -> m a++  -- | Left biased union.+  --+  --   /Axioms:/+  --+  -- * @unionl = unionwith (\\x y -> x)@+  --+  --   This function is /unambiguous/.+  unionl             :: m a -> m a -> m a++  -- | Right biased union.+  --+  --   /Axioms:/+  --+  -- * @unionr = unionWith (\\x y -> y)@+  --+  --   This function is /unambiguous/.+  unionr             :: m a -> m a -> m a++  -- | Same as 'union', but with a combining function to resolve duplicates.+  --+  --   This function is /unambiguous/.+  unionWith          :: (a -> a -> a) -> m a -> m a -> m a++  -- | Same as 'unionSeq', but with a combining function to resolve duplicates.+  --+  --   This function is /unambiguous/.+  unionSeqWith       :: Sequence seq => (a -> a -> a) -> seq (m a) -> m a++  -- | Compute the intersection of two finite maps.  The resulting finite map+  --   will contain bindings where the keys are the set intersection of the+  --   keys in the argument finite maps.  The combining function computes+  --   the value of the element given the bound elements from the argument+  --   finite maps.+  --+  --   This function is /unambiguous/.+  intersectionWith   :: (a -> b -> c) -> m a -> m b -> m c++  -- | Computes the difference of two finite maps; that is, all bindings+  --   in the first finite map whose keys to not appear in the second.+  --+  --   This function is always /unambiguous/.+  difference         :: m a -> m b -> m a++  -- | Test whether the set of keys in the first finite map is a proper subset+  --   of the set of keys of the second; that is, every key present in+  --   the first finite map is also a member of the second finite map AND+  --   there exists some key in the second finite map which is not present+  --   in the first.+  --+  --   This function is always /unambiguous/.+  properSubset       :: m a -> m b -> Bool++  -- | Test whether the set of keys in the first finite map is a subset of+  --   the set of keys of the second; that is, if every key present in the first+  --   finite map is also present in the second.+  --+  --   This function is always /unambiguous/.+  subset             :: m a -> m b -> Bool++  -- | Test whether the first map is a submap of the second map given a comparison+  --   function on elements; that is, if every key present in the first map is also+  --   present in the second map and the comparison function returns true when applied+  --   two the bound elements.+  --+  --   This function is always /unambiguous/.+  submapBy           :: (a -> a -> Bool) -> m a -> m a -> Bool++  -- | Test whether the first map is a proper submap of the second map given a comparison+  --   function on elements; that is, if every key present in the first map is also+  --   present in the second map and the comparison function returns true when applied+  --   two the bound elements AND there exiss some key in the second finite map which+  --   is not present in the first.+  --+  --   This function is always /unambiguous/.+  properSubmapBy     :: (a -> a -> Bool) -> m a -> m a -> Bool++  -- | Test whether the first map is the \"same\" map as the second map given a comparison+  --   function on elements; that is, if the first and second maps have the same set of keys+  --   and the comparison function returns true when applied to corresponding elements.+  --+  --   This function is always /unambiguous/.+  sameMapBy          :: (a -> a -> Bool) -> m a -> m a -> Bool++-- | Finite maps where the keys additionally have an ordering relation.+--   This class introduces no new methods.+class (OrdAssocX m k, FiniteMapX m k) => OrdFiniteMapX m k | m -> k++-- | Associative collections where the keys are observable.+class AssocX m k => Assoc m k | m -> k where+  -- | Extract the bindings of an associative collection into a+  --   sequence. The bindings are emitted in an unspecified order.+  --+  --   This function is /ambiguous/ with respect to the sequence order+  --   iff the associative collection contains more than one binding.+  --   Furthermore, it is /ambiguous/ with respect to the actual key+  --   returned, unless the @Eq@ instance on keys corresponds to+  --   indistinguisability.+  toSeq             :: Sequence seq => m a -> seq (k,a)++  -- | Extract the keys of an associative collection into a sequence.+  --   The keys are emitted in an unspecified order.  For finite relations,+  --   keys which appear multiple times in the relation will appear as many+  --   times in the extracted sequence.+  --+  --   This function is /ambiguous/ with respect to the sequence order+  --   iff the associative collection contains more than one binding.+  --   Furthermore, it is /ambiguous/ with respect to the actual key+  --   returned, unless the @Eq@ instance on keys corresponds to+  --   indistinguisability.+  keys              :: Sequence seq => m a -> seq k++  -- | Apply a function to every element in an associative collection.  The+  --   mapped function additionally takes the value of the key.+  --+  --   This function is /ambiguous/ with respect to the actual keys+  --   observed, unless the @Eq@ instance on keys corresponds to+  --   indistinguisability.+  mapWithKey        :: (k -> a -> b) -> m a -> m b++  -- | Combine all the elements in the associative collection, given a combining+  --   function and an initial value.  The elements are processed in an+  --   unspecified order.  The combining function additionally takes the+  --   value of the key.+  --+  --   @foldWithKey f@ is /unambiguous/ iff @f@ is fold-commutative and+  --   the @Eq@ instance on keys corresponds to indistinguisability.+  foldWithKey       :: (k -> a -> b -> b) -> b -> m a -> b++  -- | A strict variant of 'foldWithKey'.+  --+  --   @foldWithKey' f@ is /unambiguous/ iff @f@ is fold-commutative and+  --   the @Eq@ instance on keys corresponds to indistinguisability.+  foldWithKey'      :: (k -> a -> b -> b) -> b -> m a -> b++  -- | Extract all bindings from an associative collection which satisfy the+  --   given predicate.+  --+  --   This function is /ambiguous/ with respect to the actual keys+  --   observed, unless the @Eq@ instance on keys corresponds to+  --   indistinguisability.+  filterWithKey     :: (k -> a -> Bool) -> m a -> m a++  -- | Split an associative collection into two sub-collections containing those+  --   bindings which satisfy the given predicate and those which do not.+  --+  --   This function is /ambiguous/ with respect to the actual keys+  --   observed, unless the @Eq@ instance on keys corresponds to+  --   indistinguisability.+  partitionWithKey  :: (k -> a -> Bool) -> m a -> (m a, m a)++-- | An associative collection with observable keys where the keys additionally+--   have an ordering relation.++class (Assoc m k, OrdAssocX m k) => OrdAssoc m k | m -> k where+  -- | Delete the binding with the minimum key from an associative+  --   collection and return the key, the element and the remaining+  --   associative collection.  Calls 'fail' if the associative collection+  --   is empty.  Which binding is chosen if there are multiple minimum keys+  --   is unspecified.+  --+  --   This function is /ambiguous/ at finite relation types if more than one+  --   minimum key exists in the relation.  Furthermore, it is /ambiguous/+  --   with respect to the actual key observed unless the @Eq@ instance on+  --   keys corresponds to indistinguisability.+  minViewWithKey  :: (Monad rm) => m a -> rm ((k, a), m a)++  -- | Find the binding with the minimum key in an associative collection and+  --   return the key and the element.  Signals an error if the associative+  --   collection is empty.  Which binding is chosen if there are multiple+  --   minimum keys is unspecified.+  --+  --   This function is /ambiguous/ at finite relation types if more than one+  --   minimum key exists in the relation.  Furthermore, it is /ambiguous/+  --   with respect to the actual key observed unless the @Eq@ instance on+  --   keys corresponds to indistinguisability.+  minElemWithKey  :: m a -> (k,a)++  -- | Delete the binding with the maximum key from an associative+  --   collection and return the key, the element and the remaining+  --   associative collection.  Calls 'fail' if the associative collection+  --   is empty.  Which binding is chosen if there are multiple maximum keys+  --   is unspecified.+  --+  --   This function is /ambiguous/ at finite relation types if more than one+  --   maximum key exists in the relation.  Furthermore, it is /ambiguous/+  --   with respect to the actual key observed unless the @Eq@ instance on+  --   keys corresponds to indistinguisability.+  maxViewWithKey  :: (Monad rm) => m a -> rm ((k, a), m a)++  -- | Find the binding with the maximum key in an associative collection and+  --   return the key and the element.  Signals an error if the associative+  --   collection is empty.  Which binding is chosen if there are multiple+  --   maximum keys is unspecified.+  --+  --   This function is /ambiguous/ at finite relation types if more than one+  --   maximum key exists in the relation.  Furthermore, it is /ambiguous/+  --   with respect to the actual key observed unless the @Eq@ instance on+  --   keys corresponds to indistinguisability.+  maxElemWithKey  :: m a -> (k,a)++  -- | Fold over all bindings in an associative collection in non-decreasing+  --   order by key with right associativity, given a combining function+  --   and an initial value.  For finite maps, the order is increasing.+  --+  --   @foldrWithKey f@ is /ambiguous/ at finite relation types if+  --   the relation contains more than one equivalent key and+  --   @f@ is not fold-commutative OR if the @Eq@ instance on keys+  --   does not correspond to indistingusihability.+  foldrWithKey    :: (k -> a -> b -> b) -> b -> m a -> b++  -- | A strict variant of 'foldrWithKey'.+  --+  --   @foldrWithKey' f@ is /ambiguous/ at finite relation types if+  --   the relation contains more than one equivalent key and+  --   @f@ is not fold-commutative OR if the @Eq@ instance on keys+  --   does not correspond to indistingusihability.  Otherwise it+  --   is /unambiguous/.+  foldrWithKey'   :: (k -> a -> b -> b) -> b -> m a -> b++  -- | Fold over all bindings in an associative collection in non-decreasing+  --   order by key with left associativity, given a combining function+  --   and an initial value.  For finite maps, the order is increasing.+  --+  --   @foldlWithKey f@ is /ambiguous/ at finite relation types if+  --   the relation contains more than one equivalent key and+  --   @f@ is not fold-commutative OR if the @Eq@ instance on keys+  --   does not correspond to indistingusihability. Otherwise it+  --   is /unambiguous/.+  foldlWithKey    :: (b -> k -> a -> b) -> b -> m a -> b++  -- | A strict variant of 'foldlWithKey'.+  --+  --   @foldlWithKey' f@ is /ambiguous/ at finite relation types if+  --   the relation contains more than one equivalent key and+  --   @f@ is not fold-commutative OR if the @Eq@ instance on keys+  --   does not correspond to indistinguishability.  Otherwise it+  --   is /unambiguous/.+  foldlWithKey'   :: (b -> k -> a -> b) -> b -> m a -> b++  -- | Extract the bindings of an associative collection into a sequence, where+  --   the bindings are in non-decreasing order by key.  For finite maps, this+  --   is increasing order.+  --+  --   This function is /ambiguous/ at finite relation types if the relation+  --   contains more than one equivalent key, or if the @Eq@ instance on+  --   keys does not correspond to indistinguishability.+  toOrdSeq        :: Sequence seq => m a -> seq (k,a)++-- | Finite maps with observable keys.+class (Assoc m k, FiniteMapX m k) => FiniteMap m k | m -> k where+  -- | Same as 'union', but with a combining function to resolve duplicates.+  --   The combining function additionally takes the key.  Which key is kept+  --   and passed into the combining function is unspecified.+  --+  --   This function is /unambiguous/ provided that the @Eq@ instance on keys+  --   corresponds to indistinguishability.+  unionWithKey      :: (k -> a -> a -> a) -> m a -> m a -> m a++  -- | Same as 'unionSeq', but with a combining function to resolve duplicates.+  --   The combining function additionally takes the key.  Which key is+  --   kept and passed into the combining function is unspecified.+  --+  --   This function is /unambiguous/ provided that the @Eq@ instance on keys+  --   corresponds to indistinguishability.+  unionSeqWithKey   :: Sequence seq => (k -> a -> a -> a) -> seq (m a) -> m a++  -- | Same as 'intersectionWith', except that the combining function+  --   additionally takes the key value for each binding.  Which key is+  --   kept and passed into the combining function is unspecified.+  --+  --   This function is /unambiguous/ provided the @Eq@ instance on keys+  --   corresponds to indistinguishability.+  intersectionWithKey  :: (k -> a -> b -> c) -> m a -> m b -> m c++-- | Finite maps with observable keys where the keys additionally+--   have an ordering relation.  This class introduces no new methods.+class (OrdAssoc m k, FiniteMap m k) => OrdFiniteMap m k | m -> k+++-- specialize sequence operations to lists++fromList          :: AssocX m k => [(k,a)] -> m a+insertList        :: AssocX m k => [(k,a)] -> m a -> m a+unionList         :: AssocX m k => [m a] -> m a+deleteList        :: AssocX m k => [k] -> m a -> m a+lookupList        :: AssocX m k => k -> m a -> [a]+elementsList      :: AssocX m k => m a -> [a]+unsafeFromOrdList :: OrdAssocX m k => [(k,a)] -> m a+fromListWith      :: FiniteMapX m k => (a -> a -> a) -> [(k,a)] -> m a+fromListWithKey   :: FiniteMapX m k => (k -> a -> a -> a) -> [(k,a)] -> m a+insertListWith    :: FiniteMapX m k =>+                         (a -> a -> a) -> [(k,a)] -> m a -> m a+insertListWithKey :: FiniteMapX m k =>+                         (k -> a -> a -> a) -> [(k,a)] -> m a -> m a+unionListWith     :: FiniteMapX m k => (a -> a -> a) -> [m a] -> m a+toList            :: Assoc m k => m a -> [(k,a)]+keysList          :: Assoc m k => m a -> [k]+toOrdList         :: OrdAssoc m k => m a -> [(k,a)]+unionListWithKey  :: FiniteMap m k => (k -> a -> a -> a) -> [m a] -> m a++fromList = fromSeq+insertList = insertSeq+unionList = unionSeq+deleteList = deleteSeq+lookupList = lookupAll+elementsList = elements+unsafeFromOrdList = unsafeFromOrdSeq+fromListWith = fromSeqWith+fromListWithKey = fromSeqWithKey+insertListWith = insertSeqWith+insertListWithKey = insertSeqWithKey+unionListWith = unionSeqWith+toList = toSeq+keysList = keys+toOrdList = toOrdSeq+unionListWithKey = unionSeqWithKey
+ src/Data/Edison/Coll.hs view
@@ -0,0 +1,737 @@+-- |+--   Module      :  Data.Edison.Coll+--   Copyright   :  Copyright (c) 1998 Chris Okasaki+--   License     :  MIT; see COPYRIGHT file for terms and conditions+--+--   Maintainer  :  robdockins AT fastmail DOT fm+--   Stability   :  stable+--   Portability :  GHC, Hugs (MPTC and FD)+--+--   The /collection/ abstraction includes sets, bags and priority queues+--   (heaps).  Collections are defined in Edison as a set of eight classes.+--+--   All collections assume at least an equality relation of elements, and+--   may also assume an ordering relation.+--+--   The hierarchy contains a root class 'CollX' together with seven+--   subclasses satisfying one or more of three common sub-properties:+--+-- * /Uniqueness/ Each element in the collection is unique (no two+--   elements in the collection are equal).  These subclasses, indicated+--   by the name @Set@, represent sets rather than bags (multi-sets).+--+-- * /Ordering/ The elements have a total ordering and it is possible to+--   process the elements in non-decreasing order. These subclasses,+--   indicates by the @Ord@ prefix, typically represent either priority+--   queues (heaps) or sets\/bags implemented as binary search trees.+--+-- * /Observability/ An observable collection is one in which it is+--   possible to view the elements in a collection.  The @X@ suffix+--   indicates a lack of observability.  This property is discussed is+--   greater detail below.+--+--   Because collections encompass a wide range of abstractions, there is no+--   single name that is suitable for all collection type constructors.+--   However, most modules implementing collections will define a type+--   constructor named either @Bag@, @Set@, or @Heap@.+--+--   /Notes on observability/+--+--   Note that the equality relation defined by the 'Eq' class is not+--   necessarily true equality.  Very often it is merely an equivalence+--   relation, where two equivalent values may be distinguishable by other+--   means.  For example, we might consider two binary trees to be equal+--   if they contain the same elements, even if their shapes are different.+--+--   Because of this phenomenon, implementations of observable collections+--   (ie, collections where it is possible to inspect the elements) are rather+--   constrained.  Such an implementation must retain the actual elements that+--   were inserted.  For example, it is not possible in general to represent an+--   observable bag as a finite map from elements to counts, because even if we+--   know that a given bag contains, say, three elements from some equivalence+--   class, we do not necessarily know /which/ three.+--+--   On the other hand, implementations of /non-observable/ collections have+--   much greater freedom to choose abstract representations of each+--   equivalence class.  For example, representing a bag as a finite map from+--   elements to counts works fine if we never need to know /which/+--   representatives from an equivalence class are actually present.  As+--   another example, consider the 'UniqueHash' class defined in+--   "Data.Edison.Prelude".  If we know that the 'hash' function yields a +--   unique integer for each equivalence class, then we can represent a+--   collection of hashable elements simply as a collection of integers.  With+--   such a representation, we can still do many useful things like testing for+--   membership; we just can't support functions like 'fold' or 'filter' that+--   require the elements themselves, rather than the hashed values.++module Data.Edison.Coll (+    -- * Superclass aliases+    -- ** Monoid+    empty, union,++    -- * Non-observable collections+    CollX(..),+    OrdCollX(..),+    SetX(..),+    OrdSetX,++    -- * Observable collections+    Coll(..),+    OrdColl(..),+    Set(..),+    OrdSet,++    -- * Specializations of all the sequence operations to lists+    fromList,+    insertList,+    unionList,+    deleteList,+    unsafeFromOrdList,+    toList,+    lookupList,+    toOrdList,+    fromListWith,+    insertListWith,+    unionListWith,++) where++import Prelude hiding (null,foldr,foldl,foldr1,foldl1,lookup,filter)+import Data.Monoid++import Data.Edison.Prelude+import Data.Edison.Seq(Sequence)+import Data.Edison.Seq.ListSeq()+++-- | The empty collection.  Equivalant to @mempty@ from+--   the @Monoid@ instance.+--+--   This function is always /unambiguous/.+empty :: CollX c a => c+empty = mempty++-- | Merge two collections.  For sets, it is unspecified which element is+--   kept in the case of duplicates.  Equivalant to @mappend@ from the+--   @Monoid@ instance.+--+--   This function is /ambiguous/ at set types if the sets are not disjoint.+--   Otherwise it is /unambiguous/.+union :: CollX c a => c -> c -> c+union = mappend+++-- | This is the root class of the collection hierarchy.  However, it+--   is perfectly adequate for many applications that use sets or bags.+class (Eq a,Monoid c) => CollX c a | c -> a where+  -- | create a singleton collection+  --+  --   This function is always /unambiguous/.+  singleton      :: a -> c++  -- | Convert a sequence to a collection.  For sets, it is unspecified+  --   which element is kept in case of duplicates.+  --+  --   This function is /ambiguous/ at set types if more than one+  --   equivalent item is in the sequence.  Otherwise it is /unambiguous/.+  fromSeq        :: Sequence seq => seq a -> c++  -- | Merge a sequence of collections.  For sets, it is unspecified which+  --   element is kept in the case of duplicates.+  --+  --   This function is /ambiguous/ at set types if the sets in the sequence+  --   are not mutually disjoint. Otherwise it is /unambiguous/.+  unionSeq :: Sequence seq => seq c -> c++  -- | Insert an element into a collection.  For sets, if an equal element+  --   is already in the set, the newly inserted element is kept, and the+  --   old element is discarded.+  --+  --   This function is always /unambiguous/.+  insert         :: a -> c -> c++  -- | Insert a sequence of elements into a collection.  For sets,+  --   the behavior with regard to multiple equal elements is unspecified.+  --+  --   This function is /ambiguous/ at set types if the sequence contains+  --   more than one equivalent item or an item which is already in the set.+  --   Otherwise it is /unambiguous/.+  insertSeq      :: Sequence seq => seq a -> c -> c++  -- | Delete a single occurrence of the given element from a collection.+  --   For bags, it is unspecified which element will be deleted.+  --+  --   This function is /ambiguous/ at bag types if more than one item exists+  --   in the bag equivalent to the given item.  Otherwise it is /unambiguous/.+  delete         :: a -> c -> c++  -- | Delete all occurrences of an element from a collection.  For sets+  --   this operation is identical to 'delete'.+  --+  --   This function is always /unambiguous/.+  deleteAll      :: a -> c -> c++  -- | Delete a single occurrence of each of the given elements from+  --   a collection.  For bags, there may be multiple occurrences of a+  --   given element in the collection, in which case it is unspecified+  --   which is deleted.+  --+  --   This function is /ambiguous/ at bag types if more than one item+  --   exists in the bag equivalent to any item in the list and the number+  --   of equivalent occurrences of that item in the sequence is less than+  --   the number of occurrences in the bag.  Otherwise it is /unambiguous/.+  deleteSeq      :: Sequence seq => seq a -> c -> c++  -- | Test whether the collection is empty.+  --+  -- /Axioms:/+  --+  -- * @null xs = (size xs == 0)@+  --+  --   This function is always /unambiguous/.+  null           :: c -> Bool++  -- | Return the number of elements in the collection.+  --+  --   This function is always /unambiguous/.+  size           :: c -> Int++  -- | Test whether the given element is in the collection.+  --+  -- /Axioms:/+  --+  -- * @member x xs = (count x xs > 0)@+  --+  --   This function is always /unambiguous/.+  member         :: a -> c -> Bool++  -- | Count how many copies of the given element are in the collection.+  --   For sets, this will always return 0 or 1.+  --+  --   This function is always /unambiguous/.+  count          :: a -> c -> Int++  -- | Semanticly, this function is a partial identity function.  If the+  --   datastructure is infinite in size or contains exceptions or non-termination+  --   in the structure itself, then @strict@ will result in bottom.  Operationally,+  --   this function walks the datastructure forcing any closures.  In many+  --   collections, the collction \"shape\" depends on the value of the elemnts;+  --   in such cases, the values of the elements will be forced to the extent+  --   necessary to force the structure of the collection, but no further.+  --+  --   This function is always /unambiguous/.+  strict         :: c -> c++  -- | A method to facilitate unit testing.  Returns 'True' if the structural+  --   invariants of the implementation hold for the given collection.  If+  --   this function returns 'False', it represents a bug; generally, either+  --   the implementation itself is flawed, or an unsafe operation has been+  --   used while violating the preconditions.+  structuralInvariant :: c -> Bool++  -- | The name of the module implementing @c@+  instanceName   :: c -> String+++-- | Collections for which the elements have an ordering relation.++class (CollX c a, Ord a) => OrdCollX c a | c -> a where++  -- | Delete the minimum element from the collection.  If there is more+  --   than one minimum, it is unspecified which is deleted.  If the collection+  --   is empty, it will be returned unchanged.+  --+  --   This function is /ambiguous/ at bag types if more than one minimum+  --   element exists in the bag.  Otherwise it is /unambiguous/.+  deleteMin          :: c -> c++  -- | Delete the maximum element from the collection.  If there is more+  --   than one maximum, it is unspecified which is deleted.  If the collection+  --   is empty, it will be returned unchanged.+  --+  --   This function is /ambiguous/ at bag types if more than one maximum+  --   element exists in the bag.  Otherwise it is /unambiguous/.+  deleteMax          :: c -> c++  -- | Insert an element into a collection which is guaranteed to be+  --   @\<=@ any existing elements in the collection.  For sets, the+  --   precondition is strengthened to @\<@.+  --+  --   This function is /unambiguous/, under the above preconditions.+  unsafeInsertMin    :: a -> c -> c++  -- | Insert an element into a collection which is guaranteed to be+  --   @>=@ any existing elements in the collection.  For sets, the +  --   precondition is strengthened to @>@.+  --+  --   This function is /unambiguous/, under the above preconditions.+  unsafeInsertMax    :: a -> c -> c++  -- | Convert a sequence in non-decreasing order into a collection.+  --   For sets, the sequence must be in increasing order.+  --+  --   This function is /unambiguous/, under the above preconditions.+  unsafeFromOrdSeq   :: Sequence seq => seq a -> c++  -- | Union two collections where every element in the first+  --   collection is @\<=@ every element in the second collection.+  --   For sets, this precondition is strengthened to @\<@.+  --+  --   This function is /unambiguous/, under the above preconditions.+  unsafeAppend       :: c -> c -> c++  -- | Extract the sub-collection of elements @\<@ the given element.+  --+  -- /Axioms:/+  --+  -- * @filterLT x xs = filter (\< x) xs@+  --+  --  This function is always /unambiguous/.+  filterLT           :: a -> c -> c++  -- | Extract the sub-collection of elements @\<=@ the given element.+  --+  -- /Axioms:/+  --+  -- * @filterLE x xs = filter (\<= x) xs@+  --+  --  This function is always /unambiguous/.+  filterLE           :: a -> c -> c++  -- | Extract the sub-collection of elements @>@ the given element.+  --+  -- /Axioms:/+  --+  -- * @filterGT x xs = filter (> x) xs@+  --+  --  This function is always /unambiguous/.+  filterGT           :: a -> c -> c++  -- | Extract the sub-collection of elements @>=@ the given element.+  --+  -- /Axioms:/+  --+  -- * @filterGE x xs = filter (>= x) xs@+  --+  --  This function is always /unambiguous/.+  filterGE           :: a -> c -> c++  -- | Split a collection into those elements @\<@ a given element and+  --   those @>=@.+  --+  -- /Axioms:/+  --+  -- * @partitionLT_GE xs = partition (\<) xs@+  --+  --  This function is always /unambiguous/.+  partitionLT_GE     :: a -> c -> (c, c)++  -- | Split a collection into those elements @\<=@ a given element and+  --   those @>@.+  --+  -- /Axioms:/+  --+  -- * @partitionLE_GT xs = partition (\<=) xs@+  --+  --  This function is always /unambiguous/.+  partitionLE_GT     :: a -> c -> (c, c)++  -- | Split a collection into those elements @\<@ a given element and+  --   those @>@.  All elements equal to the given element are discarded.+  --+  -- /Axioms:/+  --+  -- *@partitionLT_GT x xs = (filterLT x xs,filterGT x xs)@+  --+  --  This function is always /unambiguous/.+  partitionLT_GT     :: a -> c -> (c, c)+++-- | A collection where the set property is maintained; that is, a set+--   contains at most one element of the equivalence class formed by the+--   'Eq' instance on the elements.+class CollX c a => SetX c a | c -> a where++  -- | Computes the intersection of two sets.  It is unspecified which +  --   element is kept when equal elements appear in each set.+  --+  --   This function is /ambiguous/, except when the sets are disjoint.+  intersection :: c -> c -> c++  -- | Computes the difference of two sets; that is, all elements in+  --   the first set which are not in the second set.+  --+  --   This function is always /unambiguous/.+  difference  :: c -> c -> c++  -- | Computes the symmetric difference of two sets; that is, all elements+  --   which appear in exactily one of the two sets.+  --+  --   This function is always /unambiguous/.+  symmetricDifference :: c -> c -> c++  -- | Test whether the first set is a proper subset of the second set;+  --   that is, if every element in the first set is also a member of the+  --   second set AND there exists some element in the second set which+  --   is not present in the first.+  --+  --   This function is always /unambiguous/.+  properSubset  :: c -> c -> Bool++  -- | Test whether the first set is a subset of the second set; that is, if+  --   every element in the first set is also a member of the second set.+  --+  --   This function is always /unambiguous/.+  subset        :: c -> c -> Bool+++-- | Sets where the elements also have an ordering relation.+--   This class contains no methods; it is only an abbreviation for+--   the context @(OrdCollX c a,SetX c a)@.++class (OrdCollX c a, SetX c a) => OrdSetX c a | c -> a+  -- no methods++-- | Collections with observable elements.  See the module documentation for+--   comments on observability.++class CollX c a => Coll c a | c -> a where++  -- | List the elements of the collection in an unspecified order.+  --+  --   This function is /ambiguous/ iff the collection contains more+  --   than one element.+  toSeq      :: Sequence seq => c -> seq a++  -- | Lookup one element equal to the given element.  If no elements+  --   exist in the collection equal to the given element, an error is+  --   signaled.  If multiple copies of the given element exist in the+  --   collection, it is unspecified which is returned.+  --+  --   This function is /ambiguous/ at bag types, when more than one+  --   element equivalent to the given item is in the bag.  Otherwise+  --   it is /unambiguous/.+  lookup     :: a -> c -> a++  -- | Lookup one element equal to the given element.  If no elements+  --   exist in the collection equal to the given element, 'fail' is called.+  --   If multiple copies of the given element exist in the collection, it+  --   is unspecified which is returned.+  --+  --   This function is /ambiguous/ at bag types, when more than one+  --   element equivalent to the given item is in the bag.  Otherwise+  --   it is /unambiguous/.+  lookupM    :: (Monad m) => a -> c -> m a++  -- | Return a sequence containing all elements in the collection equal to+  --   the given element in an unspecified order.+  --+  --   This function is /ambiguous/ at bag types, when more than one+  --   element equivalent to the given item is in the bag.  Otherwise+  --   it is /unambiguous/.+  lookupAll  :: Sequence seq => a -> c -> seq a++  -- | Lookup one element equal to the (second) given element in the collection.+  --   If no elements exist in the collection equal to the given element, then+  --   the default element is returned.+  --+  --   This function is /ambiguous/ at bag types, when more than one+  --   element equivalent to the given item is in the bag.  Otherwise+  --   it is /unambiguous/.+  lookupWithDefault  :: a -- ^ default element+                     -> a -- ^ element to lookup+                     -> c -- ^ collection+                     -> a++  -- | Fold over all the elements in a collection in an unspecified order.+  --+  --   @fold f@ is /unambiguous/ iff @f@ is fold-commutative.+  fold       :: (a -> b -> b) -> b -> c -> b++  -- | A strict variant of 'fold'.+  --+  --   @fold' f@ is /unambiguous/ iff @f@ is fold-commutative.+  fold'      :: (a -> b -> b) -> b -> c -> b++  -- | Fold over all the elements in a collection in an unspecified order.+  --   An error is signaled if the collection is empty.+  --+  --   @fold1 f@ is /unambiguous/ iff @f@ is fold-commutative.+  fold1      :: (a -> a -> a) -> c -> a++  -- | A strict variant of 'fold1'.+  --+  --   @fold1' f@ is /unambiguous/ iff @f@ is fold-commutative.+  fold1'     :: (a -> a -> a) -> c -> a++  -- | Remove all elements not satisfying the predicate.+  --+  --   This function is always /unambiguous/.+  filter     :: (a -> Bool) -> c -> c++  -- | Returns two collections, the first containing all the elements+  --   satisfying the predicate, and the second containing all the+  --   elements not satisfying the predicate.+  --+  --   This function is always /unambiguous/.+  partition  :: (a -> Bool) -> c -> (c, c)++  -- | Similar to 'strict', this function walks the datastructure forcing closures.+  --   However, @strictWith@ will additionally apply the given function to the+  --   collection elements, force the result using @seq@, and then ignore it.+  --   This function can be used to perform various levels of forcing on the+  --   sequence elements.  In particular:+  --+  -- > strictWith id xs+  --+  --   will force the spine of the datastructure and reduce each element to WHNF.+  --+  --   This function is always /unambiguous/.+  strictWith :: (a -> b) -> c -> c+++-- | Collections with observable elements where the elements additionally+--   have an ordering relation.  See the module documentation for comments+--   on observability.++class (Coll c a, OrdCollX c a) => OrdColl c a | c -> a where++  -- | Return the minimum element in the collection, together with+  --   the collection without that element.  If there are multiple+  --   copies of the minimum element, it is unspecified which is chosen.+  --   /Note/ that 'minView', 'minElem', and 'deleteMin' may make different+  --   choices.  Calls 'fail' if the collection is empty.+  --+  --   This function is /ambiguous/ at bag types, if more than one minimum+  --   element exists in the bag.  Otherwise, it is /unambiguous/.+  minView    :: (Monad m) => c -> m (a, c)++  -- | Return the minimum element in the collection.  If there are multiple+  --   copies of the minimum element, it is unspecified which is chosen.+  --   /Note/ that 'minView', 'minElem', and 'deleteMin' may make different+  --   choices.  Signals an error if the collection is empty.+  --+  --   This function is /ambiguous/ at bag types, if more than one minimum+  --   element exists in the bag.  Otherwise, it is /unambiguous/.+  minElem    :: c -> a++  -- | Return the maximum element in the collection, together with +  --   the collection without that element.  If there are multiple+  --   copies of the maximum element, it is unspecified which is chosen.+  --   /Note/ that 'maxView', 'maxElem' and 'deleteMax' may make different+  --   choices.  Calls 'fail' if the collection is empty.+  --+  --   This function is /ambiguous/ at bag types, if more than one maximum+  --   element exists in the bag.  Otherwise, it is /unambiguous/.+  maxView    :: (Monad m) => c -> m (a, c)++  -- | Return the maximum element in the collection.  If there are multiple+  --   copies of the maximum element, it is unspecified which is chosen.+  --   /Note/ that 'maxView', 'maxElem' and 'deleteMax' may make different+  --   choices.  Signals an error if the collection is empty.+  --+  --   This function is /ambiguous/ at bag types, if more than one maximum+  --   element exists in the bag.  Otherwise, it is /unambiguous/.+  maxElem    :: c -> a++  -- | Fold across the elements in non-decreasing order with right+  --   associativity. (For sets, this will always be increasing order)+  --+  --   This function is /unambiguous/ if the combining function is+  --   fold-commutative, at all set types, and at bag types+  --   where no two equivalent elements exist in the bag.  Otherwise+  --   it is /ambiguous/.+  foldr      :: (a -> b -> b) -> b -> c -> b++  -- | A strict variant of 'foldr'.+  --+  --   This function is /unambiguous/ if the combining function is+  --   fold-commutative, at all set types, and at bag types+  --   where no two equivalent elements exist in the bag.  Otherwise+  --   it is /ambiguous/.+  foldr'     :: (a -> b -> b) -> b -> c -> b++  -- | Fold across the elements in non-decreasing order with left+  --   associativity. (For sets, this will always be increasing order)+  --+  --   This function is /unambiguous/ if the combining function is+  --   fold-commutative, at all set types, and at bag types+  --   where no two equivalent elements exist in the bag.  Otherwise+  --   it is /ambiguous/.+  foldl      :: (b -> a -> b) -> b -> c -> b++  -- | A strict variant of 'foldl'.+  --+  --   This function is /unambiguous/ if the combining function is+  --   fold-commutative, at all set types, and at bag types+  --   where no two equivalent elements exist in the bag.  Otherwise+  --   it is /ambiguous/.+  foldl'     :: (b -> a -> b) -> b -> c -> b++  -- | Fold across the elements in non-decreasing order with right+  --   associativity, or signal an error if the collection is empty.+  --   (For sets, this will always be increasing order)+  --+  --   This function is /unambiguous/ if the combining function is+  --   fold-commutative, at all set types, and at bag types+  --   where no two equivalent elements exist in the bag.  Otherwise+  --   it is /ambiguous/.+  foldr1     :: (a -> a -> a) -> c -> a++  -- | A strict variant of 'foldr1'.+  --+  --   This function is /unambiguous/ if the combining function is+  --   fold-commutative, at all set types, and at bag types+  --   where no two equivalent elements exist in the bag.  Otherwise+  --   it is /ambiguous/.+  foldr1'    :: (a -> a -> a) -> c -> a++  -- | Fold across the elements in non-decreasing order with left+  --   associativity, or signal an error if the collection is empty.+  --   (For sets, this will always be increasing order)+  --+  --   This function is /unambiguous/ if the combining function is+  --   fold-commutative, at all set types, and at bag types+  --   where no two equivalent elements exist in the bag.  Otherwise+  --   it is /ambiguous/.+  foldl1     :: (a -> a -> a) -> c -> a++  -- | A strict variant of 'foldl1'.+  --+  --   This function is /unambiguous/ if the combining function is+  --   fold-commutative, at all set types, and at bag types+  --   where no two equivalent elements exist in the bag.  Otherwise+  --   it is /ambiguous/.+  foldl1'    :: (a -> a -> a) -> c -> a++  -- | List the elements in non-decreasing order. (For sets, this will always+  --   be increasing order)+  --+  --   At set types, this function is /unambiguous/.  At bag types, it+  --   is /unambiguous/ if no two equivalent elements exist in the bag;+  --   otherwise it is /ambiguous/.+  toOrdSeq   :: Sequence seq => c -> seq a++  -- | Map a monotonic function across all elements of a collection.  The +  --   function is required to satisfy the following precondition:+  --+  -- > forall x y. x < y ==> f x < f y+  --+  --   This function is /unambiguous/, under the precondition.+  unsafeMapMonotonic :: (a -> a) -> c -> c++++-- | Collections with observable elements where the set property is maintained;+--   that is, a set contains at most one element of the equivalence class+--   formed by the 'Eq' instance on the elements.+--+--   /WARNING: Each of the following \"With\" functions is unsafe./ +--   The passed in combining functions are used to choose which element is kept+--   in the case of duplicates. They are required to satisfy the precondition+--   that, given two equal elements, they return a third element equal to the+--   other two.  Usually, the combining function just returns its first or+--   second argument, but it can combine elements in non-trivial ways.+--+--   The combining function should usually be associative.  Where the function+--   involves a sequence of elements, the elements will be combined from+--   left-to-right, but with an unspecified associativity.+--+--   For example, if @x == y == z@,+--   then @fromSeqWith (+) [x,y,z]@ equals either+--     @single (x + (y + z))@+--   or+--     @single ((x + y) + z)@++class (Coll c a, SetX c a) => Set c a | c -> a where++  -- | Same as 'fromSeq' but with a combining function to resolve duplicates.  +  --+  --   This function is /unambiguous/ under the \"with\" precondition+  --   if the combining function is associative.  Otherwise it is /ambiguous/.+  fromSeqWith     :: Sequence seq => (a -> a -> a) -> seq a -> c++  -- | Same as 'insert' but with a combining function to resolve duplicates.+  --+  --   This function is /unambiguous/ under the \"with\" precondition.+  insertWith      :: (a -> a -> a) -> a -> c -> c++  -- | Same as 'insertSeq' but with a combining function to resolve duplicates.+  --+  --   This function is /unambiguous/ under the \"with\" precondition+  --   if the combining function is associative.  Otherwise it is /ambiguous/.+  insertSeqWith   :: Sequence seq => (a -> a -> a) -> seq a -> c -> c++  -- | Left biased union.+  --+  --   /Axioms:/+  --+  -- * @unionl = unionWith (\\x y -> x)@+  --+  --   This function is always /unambiguous/.+  unionl          :: c -> c -> c+ +  -- | Right biased union.+  --+  --   /Axioms:/+  --+  -- * @unionr = unionWith (\\x y -> y)@+  --+  --  This function is always /unambiguous/.+  unionr          :: c -> c -> c++  -- | Same as 'union', but with a combining function to resolve duplicates.    +  --+  --   This function is /unambiguous/ under the \"with\" precondition.+  unionWith       :: (a -> a -> a) -> c -> c -> c++  -- | Same as 'unionSeq', but with a combining function to resolve duplicates.+  --+  --   This function is /unambiguous/ under the \"with\" precondition+  --   if the combining function is associative.  Otherwise it is /ambiguous/.+  unionSeqWith    :: Sequence seq => (a -> a -> a) -> seq (c) -> c++  -- | Same as 'intersection', but with a combining function to resolve duplicates.+  --+  --  This function is /unambiguous/ under the \"with\" precondition.+  intersectionWith   :: (a -> a -> a) -> c -> c -> c+++++-- | Collections with observable elements where the set property is maintained+--   and where additionally, there is an ordering relation on the elements.+--   This class introduces no new methods, and is simply an abbreviation +--   for the context:+--+--   @(OrdColl c a,Set c a)@++class (OrdColl c a, Set c a) => OrdSet c a | c -> a+  -- no methods+++-- specialize all the sequence operations to lists++fromList          :: CollX c a => [a] -> c+insertList        :: CollX c a => [a] -> c -> c+unionList         :: CollX c a => [c] -> c+deleteList        :: CollX c a => [a] -> c -> c+unsafeFromOrdList :: OrdCollX c a => [a] -> c+toList            :: Coll c a => c -> [a]+lookupList        :: Coll c a => a -> c -> [a]+toOrdList         :: OrdColl c a => c -> [a]+fromListWith      :: Set c a => (a -> a -> a) -> [a] -> c+insertListWith    :: Set c a => (a -> a -> a) -> [a] -> c -> c+unionListWith     :: Set c a => (a -> a -> a) -> [c] -> c++fromList = fromSeq+insertList = insertSeq+unionList = unionSeq+deleteList = deleteSeq+unsafeFromOrdList = unsafeFromOrdSeq+toList = toSeq+lookupList = lookupAll+toOrdList = toOrdSeq+fromListWith = fromSeqWith+insertListWith = insertSeqWith+unionListWith = unionSeqWith
+ src/Data/Edison/Coll/Utils.hs view
@@ -0,0 +1,53 @@+-- |+--   Module      :  Data.Edison.Coll.Utils+--   Copyright   :  Copyright (c) 1998 Chris Okasaki+--   License     :  MIT; see COPYRIGHT file for terms and conditions+--+--   Maintainer  :  robdockins AT fastmail DOT fm+--   Stability   :  stable+--   Portability :  GHC, Hugs (MPTC and FD)+--+--   This module provides implementations of several useful operations+--   that are not included in the collection classes themselves.  This is+--   usually because the operation involves transforming a collection into a+--   different type of collection; such operations cannot be typed using+--   the collection classes without significantly complicating them.+--+--   Be aware that these functions are defined using the external class+--   interfaces and may be less efficient than corresponding, but more+--   restrictively typed, functions in the collection classes.++module Data.Edison.Coll.Utils where++import Prelude hiding (map,null,foldr,foldl,foldr1,foldl1,lookup,filter)+import Data.Edison.Coll+++-- | Apply a function across all the elements in a collection and transform+--   the collection type.+map :: (Coll cin a, CollX cout b) => (a -> b) -> (cin -> cout)+map f xs = fold (\x ys -> insert (f x) ys) empty xs+++-- | Map a partial function across all elements of a collection and transform+--   the collection type.+mapPartial :: (Coll cin a, CollX cout b) => (a -> Maybe b) -> (cin -> cout)+mapPartial f xs = fold (\ x ys -> case f x of+                                    Just y -> insert y ys+                                    Nothing -> ys)+                       empty xs+++-- | Map a monotonic function across all the elements of a collection and+--   transform the collection type.   The function is required to satisfy+--   the following precondition:+--+-- > forall x y. x < y ==> f x < f y+unsafeMapMonotonic :: (OrdColl cin a, OrdCollX cout b) => (a -> b) -> (cin -> cout)+unsafeMapMonotonic f xs = foldr (unsafeInsertMin . f) empty xs+++-- | Map a collection-producing function across all elements of a collection+--   and collect the results together using 'union'.+unionMap :: (Coll cin a, CollX cout b) => (a -> cout) -> (cin -> cout)+unionMap f xs = fold (\x ys -> union (f x) ys) empty xs
+ src/Data/Edison/Prelude.hs view
@@ -0,0 +1,64 @@+-- |+--   Module      :  Data.Edison.Prelude+--   Copyright   :  Copyright (c) 1998 Chris Okasaki+--   License     :  BSD3; see COPYRIGHT file for terms and conditions+--+--   Maintainer  :  robdockins AT fastmail DOT fm+--   Stability   :  stable+--   Portability :  GHC, Hugs (MPTC and FD)+--+--   This module is a central depository of common definitions+--   used throughout Edison.++module Data.Edison.Prelude (+-- * Hashing classes+  Hash (..)+, UniqueHash+, ReversibleHash (..)+, Measured (..)+) where++import Data.Monoid++-- | This class represents hashable objects. If obeys the +--   following invariant:+--+-- @forall x,y :: a. (x == y) implies (hash x == hash y)@++class Eq a => Hash a where+  hash :: a -> Int+++-- | This class represents hashable objects where the hash function+--   is /unique/ (injective).  There are no new methods, just a +--   stronger invariant:+--+-- @forall x,y :: a. (x == y) iff (hash x == hash y)@++class Hash a => UniqueHash a+++-- | This class represents hashable objects where the hash is+--   reversible.+--+-- @forall x :: a. unhash (hash x) == x@+--+--  Note that:+--+-- @hash (unhash i) == i@+--+-- does not necessarily hold because 'unhash' is not necessarily+-- defined for all @i@, only for all @i@ in the range of hash.++class UniqueHash a => ReversibleHash a where+  unhash :: Int -> a+++-- | This class represents a quantity that can be measured.  It is+--   calculated by an associative function with a unit (hence the+--   @Monoid@ superclass, and by a function which gives the measurement+--   for an individual item.  Some datastructures are able to speed up+--   the calculation of a measure by caching intermediate values of+--   the computation.+class (Monoid v) => Measured v a | a -> v where+  measure :: a -> v
+ src/Data/Edison/Seq.hs view
@@ -0,0 +1,1289 @@+-- |+--   Module      :  Data.Edison.Seq+--   Copyright   :  Copyright (c) 1998-1999 Chris Okasaki+--   License     :  MIT; see COPYRIGHT file for terms and conditions+--+--   Maintainer  :  robdockins AT fastmail DOT fm+--   Stability   :  stable+--   Portability :  GHC, Hugs (MPTC and FD)+--+--   The sequence abstraction is usually viewed as a hierarchy of ADTs+--   including lists, queues, deques, catenable lists, etc. However, such+--   a hierarchy is based on efficiency rather than functionality. For example,+--   a list supports all the operations that a deque supports, even though+--   some of the operations may be inefficient. Hence, in Edison, all sequence+--   data structures are defined as instances of the single Sequence class:+--+--   @   class (Functor s, MonadPlus s) => Sequence s@+--+--   All sequences are also instances of 'Functor', 'Monad', and 'MonadPlus'.+--   In addition, all sequences are expected to be instances of @Eq@, @Show@,+--   and @Read@, although this is not enforced.+--+--   We follow the naming convention that every module implementing sequences+--   defines a type constructor named @Seq@.+--+--   For each method the \"default\" complexity is listed.  Individual+--   implementations may differ for some methods.  The documentation for+--   each implementation will list those methods for which the running time+--   differs from these.+--+--   A description of each Sequence function appears below.  In most cases+--   psudeocode is also provided. Obviously, the psudeocode is illustrative only.+--   +--   Sequences are represented in psudecode between angle brackets:+--+-- > <x0,x1,x2...,xn-1>+--+--   Such that @x0@ is at the left (front) of the sequence and+--   @xn-1@ is at the right (rear) of the sequence.++module Data.Edison.Seq (+-- * Superclass aliases+-- ** Functor aliases+  map+-- ** Monad aliases+, singleton+, concatMap+-- ** MonadPlus aliases+, empty+, append++-- * The Sequence class+, Sequence (..)+) where++import Prelude hiding (concat,reverse,map,concatMap,foldr,foldl,foldr1,foldl1,+                       filter,takeWhile,dropWhile,lookup,take,drop,splitAt,+                       zip,zip3,zipWith,zipWith3,unzip,unzip3,null)++import Control.Monad+import Data.Monoid++import Data.Edison.Prelude+++-- | Return the result of applying a function to+--   every element of a sequence.  Identical+--   to @fmap@ from @Functor@.+--+-- > map f <x0,...,xn-1> = <f x0,...,f xn-1>+--+-- /Axioms:/+--+-- * @map f empty = empty@+--+-- * @map f (lcons x xs) = lcons (f x) (map f xs)@+--+--   This function is always /unambiguous/.+--+--   Default running time: @O( t * n )@+--     where @t@ is the running time of @f@+map        :: Sequence s => (a -> b) -> s a -> s b+map = fmap+++-- | Create a singleton sequence.  Identical to @return@+--   from @Monad@.+--+-- > singleton x = <x>+--+-- /Axioms:/+--+-- * @singleton x = lcons x empty = rcons x empty@+--+--   This function is always /unambiguous/.+--+--   Default running time: @O( 1 )@+singleton   :: Sequence s => a -> s a+singleton = return+++-- | Apply a sequence-producing function to every element+--   of a sequence and flatten the result. 'concatMap'+--   is the bind @(>>=)@ operation of from @Monad@ with the+--   arguments in the reverse order.+-- +-- > concatMap f xs = concat (map f xs)+--+-- /Axioms:/+--+-- * @concatMap f xs = concat (map f xs)@+--+--   This function is always /unambiguous/.+--+--   Default running time: @O( t * n + m )@+--     where @n@ is the length of the input sequence, @m@ is the+--     length of the output sequence, and @t@ is the running time of @f@+concatMap  :: Sequence s => (a -> s b) -> s a -> s b+concatMap = flip (>>=)+++-- | The empty sequence.  Identical to @mzero@+--   from @MonadPlus@.+-- +-- > empty = <>+--+--   This function is always /unambiguous/.+--  +--   Default running time: @O( 1 )@+empty       :: Sequence s => s a+empty = mzero+++-- | Append two sequence, with the first argument on the left+--   and the second argument on the right.  Identical to @mplus@+--   from @MonadPlus@.+-- +-- > append <x0,...,xn-1> <y0,...,ym-1> = <x0,...,xn-1,y0,...,ym-1>+--+-- /Axioms:/+--+-- * @append xs ys = foldr lcons ys xs@+--+--   This function is always /unambiguous/.+--+--   Default running time: @O( n1 )@+append    :: Sequence s => s a -> s a -> s a+append = mplus+++-- | The 'Sequence' class defines an interface for datatypes which+--   implement sequences.  A description for each function is+--   given below.  +class (Functor s, MonadPlus s) => Sequence s where++  -- | Add a new element to the front\/left of a sequence+  --+  -- > lcons x <x0,...,xn-1> = <x,x0,...,xn-1>+  --+  -- /Axioms:/+  --+  -- * @lcons x xs = append (singleton x) xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( 1 )@+  lcons     :: a -> s a -> s a++  -- | Add a new element to the right\/rear of a sequence+  --+  -- > rcons x <x0,...,xn-1> = <x0,...,xn-1,x>+  --+  -- /Axioms:/+  --+  -- * @rcons x xs = append xs (singleton x)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  rcons     :: a -> s a -> s a+++  -- | Convert a list into a sequence+  -- +  -- > fromList [x0,...,xn-1] = <x0,...,xn-1>+  --+  -- /Axioms:/+  --+  -- * @fromList xs = foldr lcons empty xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  fromList  :: [a] -> s a++  -- | Create a sequence containing @n@ copies of the given element.+  --   Return 'empty' if @n\<0@.+  --+  --   @copy n x = \<x,...,x>@+  --+  -- /Axioms:/+  --+  -- * @n > 0    ==> copy n x = cons x (copy (n-1) x)@+  --+  -- * @n \<= 0   ==> copy n x = empty@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  copy      :: Int -> a -> s a++  -- | Separate a sequence into its first (leftmost) element and the+  --   remaining sequence.  Calls 'fail' if the sequence is empty.+  --+  -- /Axioms:/+  --+  -- * @lview empty = fail@+  --+  -- * @lview (lcons x xs) = return (x,xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( 1 )@+  lview     :: (Monad m) => s a -> m (a, s a)++  -- | Return the first element of a sequence.+  --   Signals an error if the sequence is empty.+  --+  -- /Axioms:/+  --+  -- * @lhead empty = undefined@+  --+  -- * @lhead (lcons x xs) = x@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( 1 )@+  lhead     :: s a -> a++  -- | Returns the first element of a sequence. +  --   Calls 'fail' if the sequence is empty.+  --+  -- /Axioms:/+  --+  -- * @lheadM empty = fail@+  --+  -- * @lheadM (lcons x xs) = return x@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( 1 )@+  lheadM    :: (Monad m) => s a -> m a ++  -- | Delete the first element of the sequence.+  --   Signals error if sequence is empty.+  --+  -- /Axioms:/+  --+  -- * @ltail empty = undefined@+  --+  -- * @ltail (lcons x xs) = xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( 1 )@+  ltail     :: s a -> s a++  -- | Delete the first element of the sequence.+  --   Calls 'fail' if the sequence is empty.+  --+  -- /Axioms:/+  --+  -- * @ltailM empty = fail@+  --+  -- * @ltailM (lcons x xs) = return xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( 1 )@+  ltailM    :: (Monad m) => s a -> m (s a)++  -- | Separate a sequence into its last (rightmost) element and the+  --   remaining sequence.  Calls 'fail' if the sequence is empty.+  --+  -- /Axioms:/+  --+  -- * @rview empty = fail@+  --+  -- * @rview (rcons x xs) = return (x,xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  rview     :: (Monad m) => s a -> m (a, s a)++  -- | Return the last (rightmost) element of the sequence.+  --   Signals error if sequence is empty.+  --+  -- /Axioms:/+  --+  -- * @rhead empty = undefined@+  --+  -- * @rhead (rcons x xs) = x@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  rhead     :: s a -> a ++  -- | Returns the last element of the sequence.+  --    Calls 'fail' if the sequence is empty.+  --+  -- /Axioms:/+  --+  -- * @rheadM empty = fail@+  --+  -- * @rheadM (rcons x xs) = return x@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  rheadM    :: (Monad m) => s a -> m a++  -- | Delete the last (rightmost) element of the sequence.+  --   Signals an error if the sequence is empty.+  --+  -- /Axioms:/+  --+  -- * @rtail empty = undefined@+  --+  -- * @rtail (rcons x xs) = xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  rtail     :: s a -> s a++  -- | Delete the last (rightmost) element of the sequence.+  --   Calls 'fail' of the sequence is empty+  --+  -- /Axioms:/+  --+  -- * @rtailM empty = fail@+  --+  -- * @rtailM (rcons x xs) = return xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  rtailM    :: (Monad m) => s a -> m (s a)++  -- | Returns 'True' if the sequence is empty and 'False' otherwise.+  -- +  -- > null <x0,...,xn-1> = (n==0)+  --+  -- /Axioms:/+  --+  -- * @null xs = (size xs == 0)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( 1 )@+  null      :: s a -> Bool++  -- | Returns the length of a sequence.+  --+  -- > size <x0,...,xn-1> = n+  --+  -- /Axioms:/+  --+  -- * @size empty = 0@+  --+  -- * @size (lcons x xs) = 1 + size xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  size      :: s a -> Int++  -- | Convert a sequence to a list.+  --+  -- > toList <x0,...,xn-1> = [x0,...,xn-1]+  --+  -- /Axioms:/+  --+  -- * @toList empty = []@+  --+  -- * @toList (lcons x xs) = x : toList xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  toList    :: s a -> [a]++  -- | Flatten a sequence of sequences into a simple sequence.+  --+  -- > concat xss = foldr append empty xss+  --+  -- /Axioms:/+  --+  -- * @concat xss = foldr append empty xss@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n + m )@+  --    where @n@ is the length of the input sequence and @m@ is+  --    length of the output sequence.+  concat    :: s (s a) -> s a++  -- | Reverse the order of a sequence+  --+  -- > reverse <x0,...,xn-1> = <xn-1,...,x0>+  --+  -- /Axioms:/+  --+  -- * @reverse empty = empty@+  --+  -- * @reverse (lcons x xs) = rcons x (reverse xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  reverse      :: s a -> s a++  -- | Reverse a sequence onto the front of another sequence.+  --+  -- > reverseOnto <x0,...,xn-1> <y0,...,ym-1> = <xn-1,...,x0,y0,...,ym-1>+  --+  -- /Axioms:/+  --+  -- * @reverseOnto xs ys = append (reverse xs) ys@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n1 )@+  reverseOnto  :: s a -> s a -> s a+++  -- | Combine all the elements of a sequence into a single value,+  --   given a combining function and an initial value.  The order+  --   in which the elements are applied to the combining function+  --   is unspecified.  @fold@ is one of the few ambiguous sequence+  --   functions.+  --+  --   /Axioms:/+  --+  --   * @fold f c empty = c@+  --+  --   * @f is fold-commutative ==> fold f = foldr f = foldl f@+  --+  --   @fold f@ is /unambiguous/ iff @f@ is fold-commutative.+  --+  --   Default running type: @O( t * n )@+  --     where @t@ is the running tome of @f@.+  fold     :: (a -> b -> b) -> b -> s a -> b++  -- | A strict variant of 'fold'.  @fold'@ is one of the few ambiguous+  --   sequence functions.+  --+  --   /Axioms:/+  --+  --   * @forall a. f a _|_ = _|_ ==> fold f x xs = fold' f x xs@+  --+  --   @fold f@ is /unambiguous/ iff @f@ is fold-commutative.+  --+  --   Default running type: @O( t * n )@+  --     where @t@ is the running tome of @f@.+  fold'    :: (a -> b -> b) -> b -> s a -> b++  -- | Combine all the elements of a non-empty sequence into a+  --   single value, given a combining function. Signals an error+  --   if the sequence is empty.+  --+  --   /Axioms:/+  --+  --   * @f is fold-commutative ==> fold1 f = foldr1 f = foldl1 f@+  --+  --   @fold1 f@ is /unambiguous/ iff @f@ is fold-commutative.+  --+  --   Default running type: @O( t * n )@+  --     where @t@ is the running tome of @f@.+  fold1    :: (a -> a -> a) -> s a -> a++  -- | A strict variant of 'fold1'.+  --+  -- /Axioms:/+  --+  -- * @forall a. f a _|_ = _|_ ==> fold1' f xs = fold1 f xs@+  --+  --   @fold1' f@ is /unambiguous/ iff @f@ is fold-commutative.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  fold1'   :: (a -> a -> a) -> s a -> a++  -- | Combine all the elements of a sequence into a single value,+  --   given a combining function and an initial value.  The function+  --   is applied with right nesting.+  -- +  -- > foldr (%) c <x0,...,xn-1> = x0 % (x1 % ( ... % (xn-1 % c)))+  --+  -- /Axioms:/+  --+  -- * @foldr f c empty = c@+  --+  -- * @foldr f c (lcons x xs) = f x (foldr f c xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldr     :: (a -> b -> b) -> b -> s a -> b++  -- | Strict variant of 'foldr'.  +  --+  -- /Axioms:/+  --+  -- * @forall a. f a _|_ = _|_ ==> foldr f x xs = foldr' f x xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldr'    :: (a -> b -> b) -> b -> s a -> b++  -- | Combine all the elements of a sequence into a single value,+  --   given a combining function and an initial value.  The function+  --   is applied with left nesting.+  --+  -- > foldl (%) c <x0,...,xn-1> = (((c % x0) % x1) % ... ) % xn-1+  --+  -- /Axioms:/+  --+  -- * @foldl f c empty = c@+  --+  -- * @foldl f c (lcons x xs) = foldl f (f c x) xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldl     :: (b -> a -> b) -> b -> s a -> b++  -- | Strict variant of 'foldl'.+  -- +  -- /Axioms:/+  --+  -- * forall a. f _|_ a = _|_ ==> foldl f z xs = foldl' f z xs+  --+  --   This function is always /unambiguous/.+  -- +  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldl'    :: (b -> a -> b) -> b -> s a -> b++  -- | Combine all the elements of a non-empty sequence into a+  --   single value, given a combining function.  The function+  --   is applied with right nesting. Signals an error if the+  --   sequence is empty.+  -- +  -- > foldr1 (+) <x0,...,xn-1>+  -- >   | n==0 = error "ModuleName.foldr1: empty sequence"+  -- >   | n>0  = x0 + (x1 + ... + xn-1)+  --+  -- /Axioms:/+  --+  -- * @foldr1 f empty = undefined@+  --+  -- * @foldr1 f (rcons x xs) = foldr f x xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldr1    :: (a -> a -> a) -> s a -> a  ++  -- | Strict variant of 'foldr1'.+  --+  -- /Axioms:/+  --+  -- * forall a. f a _|_ = _|_ ==> foldr1 f xs = foldr1' f xs+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldr1'   :: (a -> a -> a) -> s a -> a++  -- | Combine all the elements of a non-empty sequence into+  --   a single value, given a combining function.  The function+  --   is applied with left nesting. Signals an error if the+  --   sequence is empty.+  --+  -- > foldl1 (+) <x0,...,xn-1>+  -- >  | n==0 = error "ModuleName.foldl1: empty sequence"+  -- >  | n>0  = (x0 + x1) + ... + xn-1+  --+  -- /Axioms:/+  --+  -- * @foldl1 f empty = undefined@+  --+  -- * @foldl1 f (lcons x xs) = foldl f x xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldl1    :: (a -> a -> a) -> s a -> a  ++  -- | Strict variant of 'foldl1'.+  -- +  -- /Axioms:/+  --+  -- * forall a. f _|_ a = _|_ ==> foldl1 f xs = foldl1' f xs+  --+  --   This function is always /unambiguous/.+  -- +  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldl1'   :: (a -> a -> a) -> s a -> a++  -- | See 'reduce1' for additional notes.+  --+  -- > reducer f x xs = reduce1 f (cons x xs)+  --+  -- /Axioms:/+  --+  -- * @reducer f c xs = foldr f c xs@ for associative @f@+  -- +  --   @reducer f@ is unambiguous iff @f@ is an associative function.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  reducer   :: (a -> a -> a) -> a -> s a -> a++  -- | Strict variant of 'reducer'.+  --+  --   See 'reduce1' for additional notes.+  --+  -- /Axioms:/+  --+  -- * @forall a. f a _|_ = _|_ && forall a. f _|_ a = _|_ ==>+  --          reducer f x xs = reducer' f x xs@+  --+  --   @reducer' f@ is unambiguous iff @f@ is an associative function.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  reducer'  :: (a -> a -> a) -> a -> s a -> a++  -- | See 'reduce1' for additional notes.+  --+  -- > reducel f x xs = reduce1 f (rcons x xs)+  --+  -- /Axioms:/+  --+  -- * @reducel f c xs = foldl f c xs@ for associative @f@+  --+  --   @reducel f@ is unambiguous iff @f@ is an associative function.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  reducel   :: (a -> a -> a) -> a -> s a -> a++  -- | Strict variant of 'reducel'.+  --+  --   See 'reduce1' for additional notes.+  --+  -- /Axioms:/+  --+  -- * @forall a. f a _|_ = _|_ && forall a. f _|_ a = _|_ ==>+  --          reducel f x xs = reducel' f x xs@+  --+  --   @reducel' f@ is unambiguous iff @f@ is an associative function.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  reducel'  :: (a -> a -> a) -> a -> s a -> a++  -- | A reduce is similar to a fold, but combines elements in a balanced fashion.+  --   The combining function should usually be associative.  If the combining+  --   function is associative, the various reduce functions yield the same+  --   results as the corresponding folds.+  --+  --   What is meant by \"in a balanced fashion\"?  We mean that+  --   @reduce1 (%) \<x0,x1,...,xn-1>@ equals some complete parenthesization of+  --   @x0 % x1 % ... % xn-1@ such that the nesting depth of parentheses+  --   is @O( log n )@.  The precise shape of this parenthesization is+  --   unspecified.+  -- +  -- > reduce1 f <x> = x+  -- > reduce1 f <x0,...,xn-1> =+  -- >     f (reduce1 f <x0,...,xi>) (reduce1 f <xi+1,...,xn-1>)+  --+  --   for some @i@ such that @ 0 \<= i && i \< n-1 @+  --+  --   Although the exact value of i is unspecified it tends toward @n\/2@+  --   so that the depth of calls to @f@ is at most logarithmic.+  --+  --   Note that @reduce@* are some of the only sequence operations for which+  --   different implementations are permitted to yield different answers.  Also+  --   note that a single implementation may choose different parenthisizations+  --   for different sequences, even if they are the same length.  This will+  --   typically happen when the sequences were constructed differently.+  --+  --   The canonical applications of the reduce functions are algorithms like+  --   merge sort where:+  --+  -- > mergesort xs = reducer merge empty (map singleton xs)+  --+  --+  -- /Axioms:/+  --+  -- * @reduce1 f empty = undefined@+  --+  -- * @reduce1 f xs = foldr1 f xs = foldl1 f xs@ for associative @f@+  --+  --   @reduce1 f@ is unambiguous iff @f@ is an associative function.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  reduce1   :: (a -> a -> a) -> s a -> a  ++  -- | Strict variant of 'reduce1'.+  --+  -- /Axioms:/+  --+  -- * @forall a. f a _|_ = _|_ && forall a. f _|_ a = _|_ ==>+  --          reduce1 f xs = reduce1' f xs@+  --+  --   @reduce1' f@ is unambiguous iff @f@ is an associative function.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  reduce1'  :: (a -> a -> a) -> s a -> a++  -- | Extract a prefix of length @i@ from the sequence.  Return+  --   'empty' if @i@ is negative, or the entire sequence if @i@+  --   is too large.+  --+  -- > take i xs = fst (splitAt i xs)+  --+  -- /Axioms:/+  --+  -- * @i \< 0        ==> take i xs = empty@+  --+  -- * @i > size xs  ==> take i xs = xs@+  --+  -- * @size xs == i ==> take i (append xs ys) = xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( i )@+  take        :: Int -> s a -> s a++  -- | Delete a prefix of length @i@ from a sequence.  Return+  --   the entire sequence if @i@ is negative, or 'empty' if+  --   @i@ is too large.+  --+  -- > drop i xs = snd (splitAt i xs)+  --+  -- /Axioms:/+  --+  -- * @i \< 0        ==> drop i xs = xs@+  --+  -- * @i > size xs  ==> drop i xs = empty@+  --+  -- * @size xs == i ==> drop i (append xs ys) = ys@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( i )@+  drop        :: Int -> s a -> s a+  +  -- | Split a sequence into a prefix of length @i@+  --   and the remaining sequence.  Behaves the same+  --   as the corresponding calls to 'take' and 'drop'+  --   if @i@ is negative or too large.+  --+  -- > splitAt i xs+  -- >  | i < 0  = (<>           , <x0,...,xn-1>)+  -- >  | i < n  = (<x0,...,xi-1>, <xi,...,xn-1>)+  -- >  | i >= n = (<x0,...,xn-1>, <>           )+  --+  -- /Axioms:/+  --+  -- * @splitAt i xs = (take i xs,drop i xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( i )@+  splitAt     :: Int -> s a -> (s a, s a)++  -- | Extract a subsequence from a sequence.  The integer+  --   arguments are \"start index\" and \"length\" NOT+  --   \"start index\" and \"end index\".  Behaves the same+  --   as the corresponding calls to 'take' and 'drop' if the+  --   start index or length are negative or too large.+  --+  -- > subseq i len xs = take len (drop i xs)+  --+  -- /Axioms:/+  --+  -- * @subseq i len xs = take len (drop i xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( i + len )@+  subseq      :: Int -> Int -> s a -> s a++  -- | Extract the elements of a sequence that satisfy the+  --   given predicate, retaining the relative ordering of+  --   elements from the original sequence.+  --+  -- > filter p xs = foldr pcons empty xs+  -- >      where pcons x xs = if p x then cons x xs else xs+  --+  -- /Axioms:/+  --+  -- * @filter p empty = empty@+  --+  -- * @filter p (lcons x xs) = if p x +  --       then lcons x (filter p xs)+  --       else filter p xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @p@+  filter      :: (a -> Bool) -> s a -> s a++  -- | Separate the elements of a sequence into those that+  --   satisfy the given predicate and those that do not,+  --   retaining the relative ordering of elements from the+  --   original sequence.+  --+  -- > partition p xs = (filter p xs, filter (not . p) xs)+  --+  -- /Axioms:/+  --+  -- * @partition p xs = (filter p xs, filter (not . p) xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @p@+  partition   :: (a -> Bool) -> s a -> (s a, s a)++  -- | Extract the maximal prefix of elements satisfying the+  --   given predicate.+  --+  -- > takeWhile p xs = fst (splitWhile p xs)+  --+  -- /Axioms:/+  --+  -- * @takeWhile p empty = empty@+  --+  -- * @takeWhile p (lcons x xs) = if p x+  --       then lcons x (takeWhile p xs)+  --       else empty@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @p@+  takeWhile   :: (a -> Bool) -> s a -> s a++  -- | Delete the maximal prefix of elements satisfying the+  --   given predicate.+  --+  -- > dropWhile p xs = snd (splitWhile p xs)+  --+  -- /Axioms:/+  --+  -- * @dropWhile p empty = empty@+  --+  -- * @dropWhile p (lcons x xs) = if p x+  --      then dropWhile p xs+  --      else lcons x xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @p@+  dropWhile   :: (a -> Bool) -> s a -> s a++  -- | Split a sequence into the maximal prefix of elements+  --   satisfying the given predicate, and the remaining sequence.+  --+  -- > splitWhile p <x0,...,xn-1> = (<x0,...,xi-1>, <xi,...,xn-1>)+  -- >   where i = min j such that p xj (or n if no such j)+  --+  -- /Axioms:/+  --+  -- * @splitWhile p xs = (takeWhile p xs,dropWhile p xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @p@+  splitWhile  :: (a -> Bool) -> s a -> (s a, s a)++  -- | Test whether an index is valid for the given sequence. All indexes+  --   are 0 based.+  --+  -- > inBounds i <x0,...,xn-1> = (0 <= i && i < n)+  --+  -- /Axioms:/+  --+  -- * @inBounds i xs = (0 \<= i && i \< size xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( i )@+  inBounds  :: Int -> s a -> Bool++  -- | Return the element at the given index.  All indexes are 0 based.+  --   Signals error if the index out of bounds.+  --+  -- > lookup i xs@<x0,...,xn-1>+  -- >   | inBounds i xs = xi+  -- >   | otherwise = error "ModuleName.lookup: index out of bounds"+  --+  -- /Axioms:/+  --+  -- * @not (inBounds i xs)  ==> lookup i xs = undefined@+  --+  -- * @size xs == i ==> lookup i (append xs (lcons x ys)) = x@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( i )@+  lookup    :: Int -> s a -> a++  -- | Return the element at the given index.  All indexes are 0 based.+  --   Calls 'fail' if the index is out of bounds.+  --+  -- > lookupM i xs@<x0,...,xn-1>+  -- >   | inBounds i xs = Just xi+  -- >   | otherwise = Nothing+  --+  -- /Axioms:/+  --+  -- * @not (inBounds i xs) ==> lookupM i xs = fail@+  --+  -- * @size xs == i ==> lookupM i (append xs (lcons x ys)) = return x@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( i )@+  lookupM   :: (Monad m) => Int -> s a -> m a++  -- | Return the element at the given index, or the+  --   default argument if the index is out of bounds.  All indexes are+  --   0 based.+  --+  -- > lookupWithDefault d i xs@<x0,...,xn-1>+  -- >   | inBounds i xs = xi+  -- >   | otherwise = d+  --+  -- /Axioms:/+  --+  -- * @not (inBounds i xs) ==> lookupWithDefault d i xs = d@+  --+  -- * @size xs == i ==> lookupWithDefault d i (append xs (lcons x ys)) = x@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( i )@+  lookupWithDefault  :: a -> Int -> s a -> a++  -- | Replace the element at the given index, or return+  --   the original sequence if the index is out of bounds.+  --   All indexes are 0 based.+  -- +  -- > update i y xs@<x0,...,xn-1>+  -- >   | inBounds i xs = <x0,...xi-1,y,xi+1,...,xn-1>+  -- >   | otherwise = xs+  --+  -- /Axioms:/+  --+  -- * @not (inBounds i xs) ==> update i y xs = xs@+  --+  -- * @size xs == i ==> update i y (append xs (lcons x ys)) =+  --      append xs (lcons y ys)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( i )@+  update    :: Int -> a -> s a -> s a++  -- | Apply a function to the element at the given index, or+  --   return the original sequence if the index is out of bounds.+  --   All indexes are 0 based.+  -- +  -- > adjust f i xs@<x0,...,xn-1>+  -- >   | inBounds i xs = <x0,...xi-1,f xi,xi+1,...,xn-1>+  -- >   | otherwise = xs+  --+  -- /Axioms:/+  --+  -- * @not (inBounds i xs) ==> adjust f i xs = xs@+  --+  -- * @size xs == i ==> adjust f i (append xs (lcons x ys)) =+  --      append xs (cons (f x) ys)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( i + t )@+  --     where @t@ is the running time of @f@+  adjust    :: (a -> a) -> Int -> s a -> s a -- map a single element++  -- | Like 'map', but include the index with each element.+  --   All indexes are 0 based.+  --+  -- > mapWithIndex f <x0,...,xn-1> = <f 0 x0,...,f (n-1) xn-1>+  --+  -- /Axioms:/+  --+  -- * @mapWithIndex f empty = empty@+  --+  -- * @mapWithIndex f (rcons x xs) = rcons (f (size xs) x) (mapWithIndex f xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  mapWithIndex    :: (Int -> a -> b) -> s a -> s b++  -- | Like 'foldr', but include the index with each element.+  --   All indexes are 0 based.+  --+  -- > foldrWithIndex f c <x0,...,xn-1> = +  -- >     f 0 x0 (f 1 x1 (... (f (n-1) xn-1 c)))+  --+  -- /Axioms:/+  --+  -- * @foldrWithIndex f c empty = c@+  --+  -- * @foldrWithIndex f c (rcons x xs) =+  --      foldrWithIndex f (f (size xs) x c) xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldrWithIndex  :: (Int -> a -> b -> b) -> b -> s a -> b++  -- | Strict variant of 'foldrWithIndex'.+  --+  -- /Axioms:/+  --+  -- * @forall i a. f i a _|_ = _|_ ==> foldrWithIndex f x xs = +  --       foldrWithIndex' f x xs@+  --+  --   This function is always /unambiguous/.+  -- +  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldrWithIndex' :: (Int -> a -> b -> b) -> b -> s a -> b++  -- | Like 'foldl', but include the index with each element.+  --   All indexes are 0 based.+  --+  -- > foldlWithIndex f c <x0,...,xn-1> =+  -- >     f (...(f (f c 0 x0) 1 x1)...) (n-1) xn-1)+  --+  -- /Axioms:/+  --+  -- * @foldlWithIndex f c empty = c@+  --+  -- * @foldlWithIndex f c (rcons x xs) =+  --      f (foldlWithIndex f c xs) (size xs) x@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldlWithIndex  :: (b -> Int -> a -> b) -> b -> s a -> b++  -- | Strict variant of 'foldlWithIndex'.+  --+  -- /Axioms:/+  --+  -- * @forall i a. f _|_ i a = _|_ ==> foldlWithIndex f x xs = +  --       foldlWithIndex' f x xs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the running time of @f@+  foldlWithIndex' :: (b -> Int -> a -> b) -> b -> s a -> b++  -- | Combine two sequences into a sequence of pairs.  If the+  --   sequences are different lengths, the excess elements of the+  --   longer sequence is discarded.+  --+  -- > zip <x0,...,xn-1> <y0,...,ym-1> = <(x0,y0),...,(xj-1,yj-1)>+  -- >     where j = min {n,m}+  --+  -- /Axioms:/+  --+  -- * @zip xs ys = zipWith (,) xs ys@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( min( n1, n2 ) )@+  zip         :: s a -> s b -> s (a,b)++  -- | Like 'zip', but combines three sequences into triples.+  --+  -- > zip3 <x0,...,xn-1> <y0,...,ym-1> <z0,...,zk-1> = +  -- >      <(x0,y0,z0),...,(xj-1,yj-1,zj-1)>+  -- >    where j = min {n,m,k}+  --+  -- /Axioms:/+  --+  -- * @zip3 xs ys zs = zipWith3 (,,) xs ys zs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( min( n1, n2, n3 ) )@+  zip3        :: s a -> s b -> s c -> s (a,b,c)++  -- | Combine two sequences into a single sequence by mapping+  --   a combining function across corresponding elements.  If+  --   the sequences are of different lengths, the excess elements+  --   of the longer sequence are discarded.+  --+  -- > zipWith f xs ys = map (uncurry f) (zip xs ys)+  --+  -- /Axioms:/+  --+  -- * @zipWith f (lcons x xs) (lcons y ys) =+  --     lcons (f x y) (zipWith f xs ys)@+  --+  -- * @(null xs || null ys) ==> zipWith xs ys = empty@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * min( n1, n2 ) )@+  --     where @t@ is the running time of @f@+  zipWith     :: (a -> b -> c) -> s a -> s b -> s c++  -- | Like 'zipWith' but for a three-place function and three+  --   sequences.+  --+  -- > zipWith3 f xs ys zs = map (uncurry f) (zip3 xs ys zs)+  --+  -- /Axioms:/+  --+  -- * @zipWith3 (lcons x xs) (lcons y ys) (lcons z zs) =+  --      lcons (f x y z) (zipWith3 f xs ys zs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * min( n1, n2, n3 ) )@+  --     where @t@ is the running time of @f@+  zipWith3    :: (a -> b -> c -> d) -> s a -> s b -> s c -> s d++  -- | Transpose a sequence of pairs into a pair of sequences.+  --+  -- > unzip xs = (map fst xs, map snd xs)+  --+  -- /Axioms:/+  --+  -- * @unzip xys = unzipWith fst snd xys@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  unzip       :: s (a,b) -> (s a, s b)++  -- | Transpose a sequence of triples into a triple of sequences+  --+  -- > unzip3 xs = (map fst3 xs, map snd3 xs, map thd3 xs)+  -- >    where fst3 (x,y,z) = x+  -- >          snd3 (x,y,z) = y+  -- >          thd3 (x,y,z) = z+  --+  -- /Axioms:/+  --+  -- * @unzip3 xyzs = unzipWith3 fst3 snd3 thd3 xyzs@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  unzip3      :: s (a,b,c) -> (s a, s b, s c)++  -- | Map two functions across every element of a sequence,+  --   yielding a pair of sequences+  --+  -- > unzipWith f g xs = (map f xs, map g xs)+  --+  -- /Axioms:/+  --+  -- * @unzipWith f g xs = (map f xs, map g xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the maximum running time+  --     of @f@ and @g@+  unzipWith   :: (a -> b) -> (a -> c) -> s a -> (s b, s c)++  -- | Map three functions across every element of a sequence,+  --   yielding a triple of sequences.+  --+  -- > unzipWith3 f g h xs = (map f xs, map g xs, map h xs)+  --+  -- /Axioms:/+  --+  -- * @unzipWith3 f g h xs = (map f xs,map g xs,map h xs)@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( t * n )@+  --     where @t@ is the maximum running time+  --     of @f@, @g@, and @h@+  unzipWith3  :: (a -> b) -> (a -> c) -> (a -> d) -> s a -> (s b, s c, s d)++  -- | Semanticly, this function is a partial identity function.  If the+  --   datastructure is infinite in size or contains exceptions or non-termination+  --   in the structure itself, then @strict@ will result in bottom.  Operationally,+  --   this function walks the datastructure forcing any closures.  Elements contained+  --   in the sequence are /not/ forced.+  --+  --   /Axioms:/+  --+  --   * @strict xs = xs@ OR @strict xs = _|_@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: @O( n )@+  strict :: s a -> s a++  -- | Similar to 'strict', this function walks the datastructure forcing closures.+  --   However, @strictWith@ will additionally apply the given function to the+  --   sequence elements, force the result using @seq@, and then ignore it.+  --   This function can be used to perform various levels of forcing on the+  --   sequence elements.  In particular:+  --+  -- > strictWith id xs+  --+  --   will force the spine of the datastructure and reduce each element to WHNF.+  --+  --   /Axioms:/+  --+  --   * forall @f :: a -> b@, @strictWith f xs = xs@ OR @strictWith f xs = _|_@+  --+  --   This function is always /unambiguous/.+  --+  --   Default running time: unbounded (forcing element closures can take arbitrairly long)+  strictWith :: (a -> b) -> s a -> s a++  -- | A method to facilitate unit testing.  Returns 'True' if the structural+  --   invariants of the implementation hold for the given sequence.  If+  --   this function returns 'False', it represents a bug in the implementation.+  structuralInvariant :: s a -> Bool++  -- | The name of the module implementing s.+  instanceName  :: s a -> String+++----------------------------------------------------------------------+-- Other possible operations not currently included+{-+  insertAt :: Int -> a -> s a -> s a+    -- adds to front or rear if index out of bounds+    --+    -- insertAt i y xs@<x0,...,xn-1>+    --    | i < 0  = cons y xs+    --    | i >= n = snoc xs y+    --    | otherwise = <x0,...,xi-1,y,xi,...,xn-1>++  deleteAt :: Int -> s a -> s a+    -- returns original sequence if index out of bounds+    --+    -- deleteAt i xs@<x0,...,xn-1>+    --    | i < 0  = xs+    --    | i >= n = xs+    --    | otherwise = <x0,...,xi-1,xi+1,...,xn-1>++  insertAt i x s = append before (cons x after)+    where (before, after) = splitAt i s++  deleteAt i s = if i < 0 then s else append before (ltail after)+    where (before, after) = splitAt i s+-}
+ src/Data/Edison/Seq/ListSeq.hs view
@@ -0,0 +1,373 @@+-- |+--   Module      :  Data.Edison.Seq.ListSeq+--   Copyright   :  Copyright (c) 1998 Chris Okasaki+--   License     :  MIT; see COPYRIGHT file for terms and conditions+--+--   Maintainer  :  robdockins AT fastmail DOT fm+--   Stability   :  stable+--   Portability :  GHC, Hugs (MPTC and FD)+--+--   This module packages the standard prelude list type as a+--   sequence.  This is the baseline sequence implementation and+--   all methods have the default running times listed in+--   "Data.Edison.Seq", except for the following two trivial operations:+--+--   * toList, fromList     @O( 1 )@+--+module Data.Edison.Seq.ListSeq (+    -- * Sequence Type+    Seq,++    -- * Sequence Operations+    empty,singleton,lcons,rcons,append,lview,lhead,lheadM,ltail,ltailM,+    rview,rhead,rheadM,rtail,rtailM,+    null,size,concat,reverse,reverseOnto,fromList,toList,map,concatMap,+    fold,fold',fold1,fold1',foldr,foldr',foldl,foldl',foldr1,foldr1',foldl1,foldl1',+    reducer,reducer',reducel,reducel',reduce1,reduce1',+    copy,inBounds,lookup,lookupM,lookupWithDefault,update,adjust,+    mapWithIndex,foldrWithIndex,foldrWithIndex',foldlWithIndex,foldlWithIndex',+    take,drop,splitAt,subseq,filter,partition,takeWhile,dropWhile,splitWhile,+    zip,zip3,zipWith,zipWith3,unzip,unzip3,unzipWith,unzipWith3,+    strict,strictWith,++    -- * Unit testing+    structuralInvariant,++    -- * Documentation+    moduleName+) where++import Prelude hiding (concat,reverse,map,concatMap,foldr,foldl,foldr1,foldl1,+                       filter,takeWhile,dropWhile,lookup,take,drop,splitAt,+                       zip,zip3,zipWith,zipWith3,unzip,unzip3,null)+import qualified Control.Monad.Identity as ID+import qualified Prelude+import Data.Edison.Prelude+import qualified Data.List+import Data.Monoid+import qualified Data.Edison.Seq as S ( Sequence(..) ) ++-- signatures for exported functions+moduleName     :: String+empty          :: [a]+singleton      :: a -> [a]+lcons          :: a -> [a] -> [a]+rcons          :: a -> [a] -> [a]+append         :: [a] -> [a] -> [a]+lview          :: (Monad rm) => [a] -> rm (a, [a])+lhead          :: [a] -> a+lheadM         :: (Monad rm) => [a] -> rm a+ltail          :: [a] -> [a]+ltailM         :: (Monad rm) => [a] -> rm [a]+rview          :: (Monad rm) => [a] -> rm (a, [a])+rhead          :: [a] -> a+rheadM         :: (Monad rm) => [a] -> rm a+rtail          :: [a] -> [a]+rtailM         :: (Monad rm) => [a] -> rm [a]+null           :: [a] -> Bool+size           :: [a] -> Int+concat         :: [[a]] -> [a]+reverse        :: [a] -> [a]+reverseOnto    :: [a] -> [a] -> [a]+fromList       :: [a] -> [a]+toList         :: [a] -> [a]+map            :: (a -> b) -> [a] -> [b]+concatMap      :: (a -> [b]) -> [a] -> [b]+fold           :: (a -> b -> b) -> b -> [a] -> b+fold'          :: (a -> b -> b) -> b -> [a] -> b+fold1          :: (a -> a -> a) -> [a] -> a+fold1'         :: (a -> a -> a) -> [a] -> a+foldr          :: (a -> b -> b) -> b -> [a] -> b+foldl          :: (b -> a -> b) -> b -> [a] -> b+foldr1         :: (a -> a -> a) -> [a] -> a+foldl1         :: (a -> a -> a) -> [a] -> a+reducer        :: (a -> a -> a) -> a -> [a] -> a+reducel        :: (a -> a -> a) -> a -> [a] -> a+reduce1        :: (a -> a -> a) -> [a] -> a+foldl'         :: (b -> a -> b) -> b -> [a] -> b+foldl1'        :: (a -> a -> a) -> [a] -> a+reducer'       :: (a -> a -> a) -> a -> [a] -> a+reducel'       :: (a -> a -> a) -> a -> [a] -> a+reduce1'       :: (a -> a -> a) -> [a] -> a+copy           :: Int -> a -> [a]+inBounds       :: Int -> [a] -> Bool+lookup         :: Int -> [a] -> a+lookupM        :: (Monad m) => Int -> [a] -> m a+lookupWithDefault :: a -> Int -> [a] -> a+update         :: Int -> a -> [a] -> [a]+adjust         :: (a -> a) -> Int -> [a] -> [a]+mapWithIndex   :: (Int -> a -> b) -> [a] -> [b]+foldrWithIndex :: (Int -> a -> b -> b) -> b -> [a] -> b+foldlWithIndex :: (b -> Int -> a -> b) -> b -> [a] -> b+foldlWithIndex' :: (b -> Int -> a -> b) -> b -> [a] -> b+take           :: Int -> [a] -> [a]+drop           :: Int -> [a] -> [a]+splitAt        :: Int -> [a] -> ([a], [a])+subseq         :: Int -> Int -> [a] -> [a]+filter         :: (a -> Bool) -> [a] -> [a]+partition      :: (a -> Bool) -> [a] -> ([a], [a])+takeWhile      :: (a -> Bool) -> [a] -> [a]+dropWhile      :: (a -> Bool) -> [a] -> [a]+splitWhile     :: (a -> Bool) -> [a] -> ([a], [a])+zip            :: [a] -> [b] -> [(a,b)]+zip3           :: [a] -> [b] -> [c] -> [(a,b,c)]+zipWith        :: (a -> b -> c) -> [a] -> [b] -> [c]+zipWith3       :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]+unzip          :: [(a,b)] -> ([a], [b])+unzip3         :: [(a,b,c)] -> ([a], [b], [c])+unzipWith      :: (a -> b) -> (a -> c) -> [a] -> ([b], [c])+unzipWith3     :: (a -> b) -> (a -> c) -> (a -> d) -> [a] -> ([b], [c], [d])+strict         :: [a] -> [a]+strictWith     :: (a -> b) -> [a] -> [a]+structuralInvariant :: [a] -> Bool++moduleName = "Data.Edison.Seq.ListSeq"++type Seq a = [a]++empty = []+singleton x = [x]+lcons = (:)+rcons x s = s ++ [x]+append = (++)++lview [] = fail "ListSeq.lview: empty sequence"+lview (x:xs) = return (x, xs)++lheadM [] = fail "ListSeq.lheadM: empty sequence"+lheadM (x:xs) = return x++lhead [] = error "ListSeq.lhead: empty sequence"+lhead (x:xs) = x++ltailM [] = fail "ListSeq.ltailM: empty sequence"+ltailM (x:xs) = return xs++ltail [] = error "ListSeq.ltail: empty sequence"+ltail (x:xs) = xs++rview [] = fail "ListSeq.rview: empty sequence"+rview xs = return (rhead xs, rtail xs)++rheadM [] = fail "ListSeq.rheadM: empty sequence"+rheadM (x:xs) = rh x xs+  where rh y [] = return y+        rh y (x:xs) = rh x xs++rhead [] = error "ListSeq.rhead: empty sequence"+rhead (x:xs) = rh x xs+  where rh y [] = y+        rh y (x:xs) = rh x xs++rtailM [] = fail "ListSeq.rtailM: empty sequence"+rtailM (x:xs) = return (rt x xs)+  where rt y [] = []+        rt y (x:xs) = y : rt x xs++rtail [] = error "ListSeq.rtail: empty sequence"+rtail (x:xs) = rt x xs+  where rt y [] = []+        rt y (x:xs) = y : rt x xs++null = Prelude.null+size = length+concat = foldr append empty+reverse = Prelude.reverse++reverseOnto [] ys = ys+reverseOnto (x:xs) ys = reverseOnto xs (x:ys)++fromList xs = xs+toList xs = xs+map = Data.List.map++concatMap = Data.List.concatMap++fold  = foldr+fold' f = foldl' (flip f)++fold1 f []      = error "ListSeq.fold1: empty sequence"+fold1 f (x:xs)  = foldr f x xs++fold1' f []     = error "ListSeq.fold1': empty sequence"+fold1' f (x:xs) = foldl' f x xs++foldr = Data.List.foldr+foldl = Data.List.foldl++foldr' f e [] = e+foldr' f e (x:xs) = f x $! foldr' f e xs++foldl' f e [] = e+foldl' f e (x:xs) = e `seq` foldl' f (f e x) xs++foldr1 f [] = error "ListSeq.foldr1: empty sequence"+foldr1 f xs = fr xs+  where fr [x]    = x+        fr (x:xs) = f x $ fr xs+        fr _ = error "ListSeq.foldr1: bug!"++foldr1' f [] = error "ListSeq.foldr1': empty sequence"+foldr1' f xs = fr xs+  where fr [x]    = x+        fr (x:xs) = f x $! fr xs+        fr _  = error "ListSeq.foldr1': bug!"++foldl1 f [] = error "ListSeq.foldl1: empty sequence"+foldl1 f (x:xs) = foldl f x xs++foldl1' f [] = error "ListSeq.foldl1': empty sequence"+foldl1' f (x:xs) = foldl' f x xs++reducer f e [] = e+reducer f e xs = f (reduce1 f xs) e++reducer' f e [] = e+reducer' f e xs = (f $! (reduce1' f xs)) $! e++reducel f e [] = e+reducel f e xs = f e (reduce1 f xs)++reducel' f e [] = e+reducel' f e xs = (f $! e) $! (reduce1' f xs)++reduce1 f [] = error "ListSeq.reduce1: empty sequence"+reduce1 f [x] = x+reduce1 f (x1 : x2 : xs) = reduce1 f (f x1 x2 : pairup xs)+  where pairup (x1 : x2 : xs) = f x1 x2 : pairup xs+        pairup xs = xs+  -- can be improved using a counter and bit ops!++reduce1' f [] = error "ListSeq.reduce1': empty sequence"+reduce1' f [x] = x+reduce1' f (x1 : x2 : xs) = x1 `seq` x2 `seq` reduce1' f (f x1 x2 : pairup xs)+  where pairup (x1 : x2 : xs) = x1 `seq` x2 `seq` (f x1 x2 : pairup xs)+        pairup xs = xs++copy n x | n <= 0 = []+         | otherwise = x : copy (n-1) x+  -- depends on n to be unboxed, should test this!++inBounds i xs+  | i >= 0    = not (null (drop i xs))+  | otherwise = False++lookup i xs = ID.runIdentity (lookupM i xs)++lookupM i xs+  | i < 0 = fail "ListSeq.lookup: not found"+  | otherwise = case drop i xs of+                  [] -> fail "ListSeq.lookup: not found"+                  (x:_) -> return x++lookupWithDefault d i xs+  | i < 0 = d+  | otherwise = case drop i xs of+                  [] -> d+                  (x:_) -> x++update i y xs +    | i < 0     = xs+    | otherwise = upd i xs+  where upd _ [] = []+        upd i (x:xs)+          | i > 0     = x : upd (i - 1) xs+          | otherwise = y : xs++adjust f i xs +    | i < 0     = xs+    | otherwise = adj i xs+  where adj _ [] = []+        adj i (x:xs)+          | i > 0     = x : adj (i - 1) xs+          | otherwise = f x : xs++mapWithIndex f = mapi 0+  where mapi i [] = []+        mapi i (x:xs) = f i x : mapi (succ i) xs++foldrWithIndex f e = foldi 0+  where foldi i [] = e+        foldi i (x:xs) = f i x (foldi (succ i) xs)++foldrWithIndex' f e = foldi 0+  where foldi i [] = e+        foldi i (x:xs) = f i x $! (foldi (succ i) xs)++foldlWithIndex f = foldi 0+  where foldi i e [] = e+        foldi i e (x:xs) = foldi (succ i) (f e i x) xs++foldlWithIndex' f = foldi 0+  where foldi i e [] = e+        foldi i e (x:xs) = e `seq` foldi (succ i) (f e i x) xs+++take i xs | i <= 0 = []+          | otherwise = Data.List.take i xs++drop i xs | i <= 0 = xs+          | otherwise = Data.List.drop i xs++splitAt i xs | i <= 0 = ([], xs)+             | otherwise = Data.List.splitAt i xs++subseq i len xs = take len (drop i xs)+        +strict l@[] = l+strict l@(_:xs) = strict xs `seq` l++strictWith f l@[] = l+strictWith f l@(x:xs) = f x `seq` strictWith f xs `seq` l++filter = Data.List.filter+partition = Data.List.partition+takeWhile = Data.List.takeWhile+dropWhile = Data.List.dropWhile+splitWhile = Data.List.span++zip = Data.List.zip+zip3 = Data.List.zip3+zipWith = Data.List.zipWith+zipWith3 = Data.List.zipWith3+unzip = Data.List.unzip+unzip3 = Data.List.unzip3++unzipWith f g = foldr consfg ([], [])+  where consfg a (bs, cs) = (f a : bs, g a : cs)+  -- could put ~ on tuple++unzipWith3 f g h = foldr consfgh ([], [], [])+  where consfgh a (bs, cs, ds) = (f a : bs, g a : cs, h a : ds)+  -- could put ~ on tuple++-- no invariants+structuralInvariant = const True++-- declare the instance++instance S.Sequence [] where+  {lcons = lcons; rcons = rcons; null = null;+   lview = lview; lhead = lhead; ltail = ltail;+   lheadM = lheadM; ltailM = ltailM;+   rview = rview; rhead = rhead; rtail = rtail;+   rheadM = rheadM; rtailM = rtailM;+   size = size; concat = concat; reverse = reverse;+   reverseOnto = reverseOnto; fromList = fromList; toList = toList;+   fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+   foldr = foldr; foldr' = foldr'; foldl = foldl; foldl' = foldl';+   foldr1 = foldr1; foldr1' = foldr1'; foldl1 = foldl1; foldl1' = foldl1';+   reducer = reducer; reducel = reducel; reduce1 = reduce1;+   reducel' = reducel'; reducer' = reducer'; reduce1' = reduce1';+   copy = copy; inBounds = inBounds; lookup = lookup;+   lookupM = lookupM; lookupWithDefault = lookupWithDefault;+   update = update; adjust = adjust; mapWithIndex = mapWithIndex; +   foldrWithIndex = foldrWithIndex; foldrWithIndex' = foldrWithIndex';+   foldlWithIndex = foldlWithIndex; foldlWithIndex' = foldlWithIndex';+   take = take; drop = drop; splitAt = splitAt; subseq = subseq;+   filter = filter; partition = partition; takeWhile = takeWhile;+   dropWhile = dropWhile; splitWhile = splitWhile; zip = zip;+   zip3 = zip3; zipWith = zipWith; zipWith3 = zipWith3; unzip = unzip;+   unzip3 = unzip3; unzipWith = unzipWith; unzipWith3 = unzipWith3;+   strict = strict; strictWith = strictWith;+   structuralInvariant = structuralInvariant; instanceName s = moduleName}
+ src/Data/Edison/Sym.hs view
@@ -0,0 +1,74 @@+-- |+--   Module      :  Data.Edison.Sym+--   Copyright   :  Copyright (c) 2006 Robert Dockins+--   License     :  MIT; see COPYRIGHT file for terms and conditions+--+--   Maintainer  :  robdockins AT fastmail DOT fm+--   Stability   :  stable+--   Portability :  GHC, Hugs (MPTC and FD)+--+--   This module introduces a number of infix symbols which are aliases+--   for some of the operations in the sequence and set abstractions.+--   For several, the argument orders are reversed to more closely+--   match usual symbolic usage.+--+--   The symbols are intended to evoke the the operations they+--   represent.  Unfortunately, ASCII is pretty limited, and Haskell 98+--   only allocates a few symbols to the operator lexical class.+--   Thus, some of the operators are less evocative than one would+--   like.  A future version of Edison may introduce unicode operators, which+--   will allow a wider range of operations to be represented symbolicly.+--+--   Unlike most of the modules in Edison, this module is intended to be+--   imported unqualified.  However, the definition of @(++)@ will conflict+--   with the Prelude definition.  Either this definition or the Prelude+--   definition will need to be imported @hiding ( (++) )@.  This definition+--   subsumes the Prelude definition, and can be safely used in place of it.++module Data.Edison.Sym where++import qualified Prelude as P+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Coll as C+import qualified Data.Edison.Coll as A++-- pull in the Sequence instance for lists to make sure (++)+-- works as advertised+import qualified Data.Edison.Seq.ListSeq+++-- | Left (front) cons on a sequence.  The new element appears on the left.+--   Identical to 'S.lcons'.+(<|) :: S.Sequence seq => a -> seq a -> seq a+(<|) = S.lcons++-- | Right (rear) cons on a sequence.  The new element appears on the right.+--   Identical to 'S.rcons' with reversed arguments.+(|>) :: S.Sequence seq => seq a -> a -> seq a+(|>) = P.flip S.rcons++-- | Append two sequences.  Identical to 'S.append'.  Subsumes the Prelude+--   definition.+(++) :: S.Sequence seq => seq a -> seq a -> seq a+(++) = S.append++-- | Lookup an element in a sequence.  Identical to 'S.lookup' with+--   reversed arguments.+(!) :: S.Sequence seq => seq a -> P.Int -> a+(!) = P.flip S.lookup++-- | Subset test operation.  Identical to 'C.subset'.+(|=) :: C.SetX set a => set -> set -> P.Bool+(|=) = C.subset++-- | Set difference.  Identical to 'C.difference'.+(\\) :: C.SetX set a => set -> set -> set+(\\) = C.difference++-- | Set intersection.  Identical to 'C.intersection'.+(/\) :: C.SetX set a => set -> set -> set+(/\) = C.intersection++-- | Set union.  Identical to 'C.union'.+(\/) :: C.SetX set a => set -> set -> set+(\/) = C.union