EdisonCore (empty) → 1.2.1
raw patch · 30 files changed
+13264/−0 lines, 30 filesdep +EdisonAPIdep +QuickCheckdep +basebuild-type:Customsetup-changed
Dependencies added: EdisonAPI, QuickCheck, base, haskell98, mtl
Files
- COPYRIGHT +23/−0
- EdisonCore.cabal +55/−0
- README +206/−0
- Setup.hs +3/−0
- src/Data/Edison/Assoc/AssocList.hs +618/−0
- src/Data/Edison/Assoc/Defaults.hs +313/−0
- src/Data/Edison/Assoc/PatriciaLoMap.hs +838/−0
- src/Data/Edison/Assoc/StandardMap.hs +372/−0
- src/Data/Edison/Assoc/TernaryTrie.hs +1149/−0
- src/Data/Edison/Coll/Defaults.hs +244/−0
- src/Data/Edison/Coll/EnumSet.hs +798/−0
- src/Data/Edison/Coll/LazyPairingHeap.hs +562/−0
- src/Data/Edison/Coll/LeftistHeap.hs +489/−0
- src/Data/Edison/Coll/MinHeap.hs +406/−0
- src/Data/Edison/Coll/SkewHeap.hs +457/−0
- src/Data/Edison/Coll/SplayHeap.hs +493/−0
- src/Data/Edison/Coll/StandardSet.hs +272/−0
- src/Data/Edison/Coll/UnbalancedSet.hs +439/−0
- src/Data/Edison/Concrete/FingerTree.hs +773/−0
- src/Data/Edison/Seq/BankersQueue.hs +419/−0
- src/Data/Edison/Seq/BinaryRandList.hs +447/−0
- src/Data/Edison/Seq/BraunSeq.hs +548/−0
- src/Data/Edison/Seq/Defaults.hs +513/−0
- src/Data/Edison/Seq/FingerSeq.hs +375/−0
- src/Data/Edison/Seq/JoinList.hs +427/−0
- src/Data/Edison/Seq/MyersStack.hs +438/−0
- src/Data/Edison/Seq/RandList.hs +481/−0
- src/Data/Edison/Seq/RevSeq.hs +382/−0
- src/Data/Edison/Seq/SimpleQueue.hs +369/−0
- src/Data/Edison/Seq/SizedSeq.hs +355/−0
+ COPYRIGHT view
@@ -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.
+ EdisonCore.cabal view
@@ -0,0 +1,55 @@+Name: EdisonCore+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 (Core Implementations)+Category: Data Structures+Stability: stable+Description:+ This package provides the core Edison data structure implementations,+ including multiple sequence, set, bag, and finite map concrete+ implementations with various performance characteristics. The+ implementations in this package have no dependencies other than+ those commonly bundled with Haskell compilers.+Hs-Source-Dirs: src+Exposed-modules:+ Data.Edison.Assoc.Defaults+ Data.Edison.Assoc.AssocList+ Data.Edison.Assoc.PatriciaLoMap+ Data.Edison.Assoc.StandardMap+ Data.Edison.Assoc.TernaryTrie+ Data.Edison.Concrete.FingerTree+ Data.Edison.Coll.Defaults+ Data.Edison.Coll.LazyPairingHeap+ Data.Edison.Coll.LeftistHeap+ Data.Edison.Coll.MinHeap+ Data.Edison.Coll.SkewHeap+ Data.Edison.Coll.SplayHeap+ Data.Edison.Coll.StandardSet+ Data.Edison.Coll.EnumSet+ Data.Edison.Coll.UnbalancedSet+ Data.Edison.Seq.Defaults+ Data.Edison.Seq.BankersQueue+ Data.Edison.Seq.BinaryRandList+ Data.Edison.Seq.BraunSeq+ Data.Edison.Seq.FingerSeq+ Data.Edison.Seq.JoinList+ Data.Edison.Seq.MyersStack+ Data.Edison.Seq.RandList+ Data.Edison.Seq.RevSeq+ Data.Edison.Seq.SimpleQueue+ Data.Edison.Seq.SizedSeq+Build-Depends:+ base >= 1.0,+ haskell98 >= 1.0,+ mtl >= 1.0,+ QuickCheck == 1.0,+ EdisonAPI == 1.2.1+Extensions:+ MultiParamTypeClasses+ FunctionalDependencies+ UndecidableInstances+ CPP+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/Assoc/AssocList.hs view
@@ -0,0 +1,618 @@+-- |+-- Module : Data.Edison.Assoc.AssocList+-- 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 implements finite maps as simple association lists.+-- +-- Duplicates are removed conceptually, but not physically. The first+-- occurrence of a given key is the one that is considered to be in the map.+--+-- The list type is mildly customized to prevent boxing the pairs.++module Data.Edison.Assoc.AssocList (+ -- * Type of simple association lists+ FM, -- instance of Assoc(X), FiniteMap(X)+ -- also instance of Functor++ -- * AssocX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,lookup,lookupM,lookupAll,+ lookupAndDelete,lookupAndDeleteM,lookupAndDeleteAll,+ lookupWithDefault,adjust,adjustAll,adjustOrInsert,adjustAllOrInsert,+ adjustOrDelete,adjustOrDeleteAll,strict,strictWith,+ map,fold,fold',fold1,fold1',filter,partition,elements,structuralInvariant,++ -- * OrdAssocX operations+ minView, minElem, deleteMin, unsafeInsertMin, maxView, maxElem, deleteMax,+ unsafeInsertMax, foldr, foldr', foldl, foldl', foldr1, foldr1', + foldl1, foldl1', unsafeFromOrdSeq, unsafeAppend,+ filterLT, filterLE, filterGT, filterGE,+ partitionLT_GE, partitionLE_GT, partitionLT_GT,++ -- * Assoc operations+ toSeq,keys,mapWithKey,foldWithKey,foldWithKey',filterWithKey,partitionWithKey,++ -- * OrdAssoc operations+ minViewWithKey, minElemWithKey, maxViewWithKey, maxElemWithKey,+ foldrWithKey, foldrWithKey', foldlWithKey, foldlWithKey', toOrdSeq,++ -- * FiniteMapX operations+ fromSeqWith,fromSeqWithKey,insertWith,insertWithKey,insertSeqWith,+ insertSeqWithKey,unionl,unionr,unionWith,unionSeqWith,intersectionWith,+ difference,properSubset,subset,properSubmapBy,submapBy,sameMapBy,+ properSubmap,submap,sameMap,++ -- * FiniteMap operations+ unionWithKey,unionSeqWithKey,intersectionWithKey,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,map,lookup,foldr,foldl,foldr1,foldl1,filter)+import qualified Prelude+import Data.Monoid+import Control.Monad.Identity+import Data.Edison.Prelude+import qualified Data.Edison.Assoc as A+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Seq.BinaryRandList as RL+import Data.Edison.Assoc.Defaults+import Test.QuickCheck (Arbitrary(..), variant)++-- signatures for exported functions+moduleName :: String+empty :: Eq k => FM k a+singleton :: Eq k => k -> a -> FM k a+fromSeq :: (Eq k,S.Sequence seq) => seq (k,a) -> FM k a+insert :: Eq k => k -> a -> FM k a -> FM k a+insertSeq :: (Eq k,S.Sequence seq) => seq (k,a) -> FM k a -> FM k a+union :: Eq k => FM k a -> FM k a -> FM k a+unionSeq :: (Eq k,S.Sequence seq) => seq (FM k a) -> FM k a+delete :: Eq k => k -> FM k a -> FM k a+deleteAll :: Eq k => k -> FM k a -> FM k a+deleteSeq :: (Eq k,S.Sequence seq) => seq k -> FM k a -> FM k a+null :: Eq k => FM k a -> Bool+size :: Eq k => FM k a -> Int+member :: Eq k => k -> FM k a -> Bool+count :: Eq k => k -> FM k a -> Int+lookup :: Eq k => k -> FM k a -> a+lookupM :: (Eq k, Monad rm) => k -> FM k a -> rm a+lookupAll :: (Eq k,S.Sequence seq) => k -> FM k a -> seq a+lookupAndDelete :: Eq k => k -> FM k a -> (a,FM k a)+lookupAndDeleteM :: (Eq k,Monad rm) => k -> FM k a -> rm (a,FM k a)+lookupAndDeleteAll :: (Eq k,S.Sequence seq) => k -> FM k a -> (seq a,FM k a)+lookupWithDefault :: Eq k => a -> k -> FM k a -> a+adjust :: Eq k => (a -> a) -> k -> FM k a -> FM k a+adjustAll :: Eq k => (a -> a) -> k -> FM k a -> FM k a+adjustOrInsert :: Eq k => (a -> a) -> a -> k -> FM k a -> FM k a+adjustAllOrInsert :: Eq k => (a -> a) -> a -> k -> FM k a -> FM k a+adjustOrDelete :: Eq k => (a -> Maybe a) -> k -> FM k a -> FM k a+adjustOrDeleteAll :: Eq k => (a -> Maybe a) -> k -> FM k a -> FM k a+strict :: FM k a -> FM k a+strictWith :: (a -> b) -> FM k a -> FM k a+map :: Eq k => (a -> b) -> FM k a -> FM k b+fold :: Eq k => (a -> b -> b) -> b -> FM k a -> b+fold1 :: Eq k => (a -> a -> a) -> FM k a -> a+fold' :: Eq k => (a -> b -> b) -> b -> FM k a -> b+fold1' :: Eq k => (a -> a -> a) -> FM k a -> a+filter :: Eq k => (a -> Bool) -> FM k a -> FM k a+partition :: Eq k => (a -> Bool) -> FM k a -> (FM k a, FM k a)+elements :: (Eq k,S.Sequence seq) => FM k a -> seq a++fromSeqWith :: (Eq k,S.Sequence seq) => + (a -> a -> a) -> seq (k,a) -> FM k a+fromSeqWithKey :: (Eq k,S.Sequence seq) => (k -> a -> a -> a) -> seq (k,a) -> FM k a+insertWith :: Eq k => (a -> a -> a) -> k -> a -> FM k a -> FM k a+insertWithKey :: Eq k => (k -> a -> a -> a) -> k -> a -> FM k a -> FM k a+insertSeqWith :: (Eq k,S.Sequence seq) => + (a -> a -> a) -> seq (k,a) -> FM k a -> FM k a+insertSeqWithKey :: (Eq k,S.Sequence seq) => + (k -> a -> a -> a) -> seq (k,a) -> FM k a -> FM k a+unionl :: Eq k => FM k a -> FM k a -> FM k a+unionr :: Eq k => FM k a -> FM k a -> FM k a+unionWith :: Eq k => (a -> a -> a) -> FM k a -> FM k a -> FM k a+unionSeqWith :: (Eq k,S.Sequence seq) => + (a -> a -> a) -> seq (FM k a) -> FM k a+intersectionWith :: Eq k => (a -> b -> c) -> FM k a -> FM k b -> FM k c+difference :: Eq k => FM k a -> FM k b -> FM k a+properSubset :: Eq k => FM k a -> FM k b -> Bool +subset :: Eq k => FM k a -> FM k b -> Bool +properSubmapBy :: Eq k => (a -> a -> Bool) -> FM k a -> FM k a -> Bool+submapBy :: Eq k => (a -> a -> Bool) -> FM k a -> FM k a -> Bool+sameMapBy :: Eq k => (a -> a -> Bool) -> FM k a -> FM k a -> Bool+properSubmap :: (Eq k, Eq a) => FM k a -> FM k a -> Bool+submap :: (Eq k, Eq a) => FM k a -> FM k a -> Bool+sameMap :: (Eq k, Eq a) => FM k a -> FM k a -> Bool++toSeq :: (Eq k,S.Sequence seq) => FM k a -> seq (k,a)+keys :: (Eq k,S.Sequence seq) => FM k a -> seq k+mapWithKey :: Eq k => (k -> a -> b) -> FM k a -> FM k b+foldWithKey :: Eq k => (k -> a -> b -> b) -> b -> FM k a -> b+foldWithKey' :: Eq k => (k -> a -> b -> b) -> b -> FM k a -> b+filterWithKey :: Eq k => (k -> a -> Bool) -> FM k a -> FM k a+partitionWithKey :: Eq k => (k -> a -> Bool) -> FM k a -> (FM k a, FM k a)++unionWithKey :: Eq k => (k -> a -> a -> a) -> FM k a -> FM k a -> FM k a+unionSeqWithKey :: (Eq k,S.Sequence seq) => + (k -> a -> a -> a) -> seq (FM k a) -> FM k a+intersectionWithKey :: Eq k => (k -> a -> b -> c) -> FM k a -> FM k b -> FM k c++minView :: (Ord k,Monad m) => FM k a -> m (a,FM k a)+minElem :: Ord k => FM k a -> a+deleteMin :: Ord k => FM k a -> FM k a+unsafeInsertMin :: Ord k => k -> a -> FM k a -> FM k a+maxView :: (Ord k,Monad m) => FM k a -> m (a,FM k a)+maxElem :: Ord k => FM k a -> a+deleteMax :: Ord k => FM k a -> FM k a+unsafeInsertMax :: Ord k => k -> a -> FM k a -> FM k a+foldr :: Ord k => (a -> b -> b) -> b -> FM k a -> b+foldr1 :: Ord k => (a -> a -> a) -> FM k a -> a+foldl :: Ord k => (b -> a -> b) -> b -> FM k a -> b+foldl1 :: Ord k => (a -> a -> a) -> FM k a -> a+foldr' :: Ord k => (a -> b -> b) -> b -> FM k a -> b+foldr1' :: Ord k => (a -> a -> a) -> FM k a -> a+foldl' :: Ord k => (b -> a -> b) -> b -> FM k a -> b+foldl1' :: Ord k => (a -> a -> a) -> FM k a -> a+unsafeFromOrdSeq :: (Ord k,S.Sequence seq) => seq (k,a) -> FM k a+unsafeAppend :: Ord k => FM k a -> FM k a -> FM k a+filterLT :: Ord k => k -> FM k a -> FM k a+filterLE :: Ord k => k -> FM k a -> FM k a+filterGT :: Ord k => k -> FM k a -> FM k a+filterGE :: Ord k => k -> FM k a -> FM k a+partitionLT_GE :: Ord k => k -> FM k a -> (FM k a,FM k a)+partitionLE_GT :: Ord k => k -> FM k a -> (FM k a,FM k a)+partitionLT_GT :: Ord k => k -> FM k a -> (FM k a,FM k a)++minViewWithKey :: (Ord k,Monad m) => FM k a -> m ((k, a), FM k a)+minElemWithKey :: Ord k => FM k a -> (k,a)+maxViewWithKey :: (Ord k,Monad m) => FM k a -> m ((k, a), FM k a)+maxElemWithKey :: Ord k => FM k a -> (k,a)+foldrWithKey :: Ord k => (k -> a -> b -> b) -> b -> FM k a -> b+foldlWithKey :: Ord k => (b -> k -> a -> b) -> b -> FM k a -> b+foldrWithKey' :: Ord k => (k -> a -> b -> b) -> b -> FM k a -> b+foldlWithKey' :: Ord k => (b -> k -> a -> b) -> b -> FM k a -> b+toOrdSeq :: (Ord k,S.Sequence seq) => FM k a -> seq (k,a)+++moduleName = "Data.Edison.Assoc.AssocList"+++data FM k a = E | I k a (FM k a)++-- no invariants+structuralInvariant :: Eq k => FM k a -> Bool+structuralInvariant = const True++---------------------------------------+-- some unexported utility functions++-- uncurried insert.+uinsert (k,x) = I k x+++-- left biased merge.+mergeFM E m = m+mergeFM m E = m+mergeFM o1@(I k1 a1 m1) o2@(I k2 a2 m2) =+ case compare k1 k2 of+ LT -> I k1 a1 (mergeFM m1 o2)+ GT -> I k2 a2 (mergeFM o1 m2)+ EQ -> I k1 a1 (mergeFM m1 m2)++toRandList E = RL.empty+toRandList (I k a m) = RL.lcons (I k a E) (toRandList m)++mergeSortFM m = RL.reducer mergeFM E (toRandList m)++foldrFM :: Eq k => (a -> b -> b) -> b -> FM k a -> b+foldrFM f z E = z+foldrFM f z (I k a m) = f a (foldrFM f z (delete k m))++foldr1FM :: Eq k => (a -> a -> a) -> FM k a -> a+foldr1FM f (I k a E) = a+foldr1FM f (I k a m) = f a (foldr1FM f (delete k m))+foldr1FM f _ = error "invalid call to foldr1FM on empty map"++foldrFM' :: Eq k => (a -> b -> b) -> b -> FM k a -> b+foldrFM' f z E = z+foldrFM' f z (I k a m) = f a $! (foldrFM' f z (delete k m))++foldr1FM' :: Eq k => (a -> a -> a) -> FM k a -> a+foldr1FM' f (I k a E) = a+foldr1FM' f (I k a m) = f a $! (foldr1FM' f (delete k m))+foldr1FM' f _ = error "invalid call to foldr1FM' on empty map"++foldlFM :: Eq k => (b -> a -> b) -> b -> FM k a -> b+foldlFM f x E = x+foldlFM f x (I k a m) = foldlFM f (f x a) (delete k m)++foldlFM' :: Eq k => (b -> a -> b) -> b -> FM k a -> b+foldlFM' f x E = x+foldlFM' f x (I k a m) = x `seq` foldlFM' f (f x a) (delete k m)++foldrWithKeyFM :: Eq k => (k -> a -> b -> b) -> b -> FM k a -> b+foldrWithKeyFM f z E = z+foldrWithKeyFM f z (I k a m) = f k a (foldrWithKeyFM f z (delete k m))++foldrWithKeyFM' :: Eq k => (k -> a -> b -> b) -> b -> FM k a -> b+foldrWithKeyFM' f z E = z+foldrWithKeyFM' f z (I k a m) = f k a $! (foldrWithKeyFM' f z (delete k m))++foldlWithKeyFM :: Eq k => (b -> k -> a -> b) -> b -> FM k a -> b+foldlWithKeyFM f x E = x+foldlWithKeyFM f x (I k a m) = foldlWithKeyFM f (f x k a) (delete k m)++foldlWithKeyFM' :: Eq k => (b -> k -> a -> b) -> b -> FM k a -> b+foldlWithKeyFM' f x E = x+foldlWithKeyFM' f x (I k a m) = x `seq` foldlWithKeyFM' f (f x k a) (delete k m)++takeWhileFM :: (k -> Bool) -> FM k a -> FM k a+takeWhileFM p E = E+takeWhileFM p (I k a m)+ | p k = I k a (takeWhileFM p m)+ | otherwise = E++dropWhileFM :: (k -> Bool) -> FM k a -> FM k a+dropWhileFM p E = E+dropWhileFM p o@(I k a m)+ | p k = dropWhileFM p m+ | otherwise = o++spanFM :: (k -> Bool) -> FM k a -> (FM k a,FM k a)+spanFM p E = (E,E)+spanFM p o@(I k a m)+ | p k = let (x,y) = spanFM p m in (I k a x,y)+ | otherwise = (E,o)+++---------------------------------------------------+-- interface functions++empty = E+singleton k x = I k x E+insert = I+insertSeq kxs m = S.foldr uinsert m kxs+fromSeq = S.foldr uinsert E++union m E = m+union E m = m+union (I k x m1) m2 = I k x (union m1 m2)++unionSeq = S.foldr union E++deleteAll key E = E+deleteAll key (I k x m) | key == k = deleteAll key m + | otherwise = I k x (deleteAll key m)++delete = deleteAll++null E = True+null (I k x m) = False++size E = 0+size (I k x m) = 1 + size (delete k m)++member key E = False+member key (I k x m) = key == k || member key m++count key E = 0+count key (I k x m) | key == k = 1+ | otherwise = count key m++lookup key m = runIdentity (lookupM key m)++lookupM key E = fail "AssocList.lookup: lookup failed"+lookupM key (I k x m) | key == k = return x+ | otherwise = lookupM key m++lookupAll key E = S.empty+lookupAll key (I k x m) | key == k = S.singleton x + | otherwise = lookupAll key m++lookupAndDelete key m = runIdentity (lookupAndDeleteM key m)++lookupAndDeleteM key E = fail "AssocList.lookupAndDeleteM: lookup failed"+lookupAndDeleteM key (I k x m)+ | key == k = return (x,delete k m)+ | otherwise = lookupAndDeleteM key m >>= + \ (z, m') -> return (z, I k x m')++lookupAndDeleteAll key m = + case lookupAndDeleteM key m of+ Nothing -> (S.empty,m)+ Just (z,m') -> (S.singleton z,m')+++lookupWithDefault d key E = d+lookupWithDefault d key (I k x m) | key == k = x+ | otherwise = lookupWithDefault d key m++elements E = S.empty+elements (I k x m) = S.lcons x (elements (delete k m))++adjust f key E = E+adjust f key (I k x m) | key == k = I key (f x) m+ | otherwise = I k x (adjust f key m)++adjustAll = adjust++adjustOrInsert f z key E = singleton key z+adjustOrInsert f z key (I k x m)+ | key == k = I key (f x) m+ | otherwise = I k x (adjustOrInsert f z key m)++adjustAllOrInsert = adjustOrInsert++adjustOrDelete = adjustOrDeleteDefault+adjustOrDeleteAll = adjustOrDeleteAllDefault++map f E = E+map f (I k x m) = I k (f x) (map f m)++fold f c E = c+fold f c (I k x m) = fold f (f x c) (delete k m)++fold' f c E = c+fold' f c (I k x m) = c `seq` fold' f (f x c) (delete k m)++fold1 f E = error "AssocList.fold1: empty map"+fold1 f (I k x m) = fold f x (delete k m)++fold1' f E = error "AssocList.fold1': empty map"+fold1' f (I k x m) = fold' f x (delete k m)++filter p E = E+filter p (I k x m) | p x = I k x (filter p (delete k m))+ | otherwise = filter p (delete k m)++partition p E = (E, E)+partition p (I k x m)+ | p x = (I k x m1,m2)+ | otherwise = (m1,I k x m2)+ where (m1,m2) = partition p (delete k m)+++toSeq E = S.empty+toSeq (I k x m) = S.lcons (k,x) (toSeq (delete k m))++keys E = S.empty+keys (I k x m) = S.lcons k (keys (delete k m))++mapWithKey f E = E+mapWithKey f (I k x m) = I k (f k x) (mapWithKey f m)++foldWithKey f c E = c+foldWithKey f c (I k x m) = foldWithKey f (f k x c) (delete k m)++foldWithKey' f c E = c+foldWithKey' f c (I k x m) = c `seq` foldWithKey' f (f k x c) (delete k m)++filterWithKey p E = E+filterWithKey p (I k x m) + | p k x = I k x (filterWithKey p (delete k m))+ | otherwise = filterWithKey p (delete k m)++partitionWithKey p E = (E, E)+partitionWithKey p (I k x m)+ | p k x = (I k x m1,m2)+ | otherwise = (m1,I k x m2)+ where (m1,m2) = partitionWithKey p (delete k m)++unionl = union+unionr = flip union+++findMin k0 x E = (k0,x)+findMin k0 a0 (I k a m)+ | k < k0 = findMin k a (delete k m)+ | otherwise = findMin k0 a0 (delete k m)++findMax k0 x E = (k0,x)+findMax k0 a0 (I k a m)+ | k > k0 = findMax k a (delete k m)+ | otherwise = findMax k0 a0 (delete k m)++minView E = fail (moduleName++".minView: empty map")+minView n@(I k a m) = let (k',x) = findMin k a m in return (x,delete k' n)++minElem E = error (moduleName++".minElem: empty map")+minElem (I k a m) = let (_,x) = findMin k a m in x++deleteMin E = error (moduleName++".deleteMin: empty map")+deleteMin n@(I k a m) = let (k',_) = findMin k a m in delete k' n++unsafeInsertMin = insert++maxView E = fail (moduleName++".maxView: empty map")+maxView n@(I k a m) = let (k',x) = findMax k a m in return (x,delete k' n)++maxElem E = error (moduleName++".maxElem: empty map")+maxElem (I k a m) = let (_,x) = findMax k a m in x++deleteMax E = error (moduleName++".deleteMax: empty map")+deleteMax n@(I k a m) = let (k',_) = findMax k a m in delete k' n++unsafeInsertMax = insert++foldr f z m = foldrFM f z (mergeSortFM m)+foldr' f z m = foldrFM' f z (mergeSortFM m)++foldr1 f m =+ case mergeSortFM m of+ E -> error $ moduleName++".foldlr1: empty map"+ m -> foldr1FM f m++foldr1' f m =+ case mergeSortFM m of+ E -> error $ moduleName++".foldlr1': empty map"+ m -> foldr1FM' f m+ +foldl f x m = foldlFM f x (mergeSortFM m)+foldl' f x m = foldlFM' f x (mergeSortFM m)++foldl1 f m =+ case mergeSortFM m of+ E -> error $ moduleName++".foldl1: empty map"+ I k a m -> foldlFM f a (delete k m)++foldl1' f m =+ case mergeSortFM m of+ E -> error $ moduleName++".foldl1': empty map"+ I k a m -> foldlFM' f a (delete k m)++unsafeFromOrdSeq = fromSeq+unsafeAppend = union+filterLT k = takeWhileFM (<k) . mergeSortFM+filterLE k = takeWhileFM (<=k) . mergeSortFM+filterGT k = dropWhileFM (<=k) . mergeSortFM+filterGE k = dropWhileFM (<k) . mergeSortFM+partitionLT_GE k = spanFM (<k) . mergeSortFM+partitionLE_GT k = spanFM (<=k) . mergeSortFM+partitionLT_GT k = (\(x,y) -> (x,delete k y)) . spanFM (<k) . mergeSortFM++minViewWithKey E = fail $ moduleName++".minViewWithKey: empty map"+minViewWithKey n@(I k a m) = let (k',x) = findMin k a m in return ((k',x),delete k' n)++minElemWithKey E = error $ moduleName++".minElemWithKey: empty map"+minElemWithKey (I k a m) = findMin k a m++maxViewWithKey E = fail $ moduleName++".maxViewWithKey: empty map"+maxViewWithKey n@(I k a m) = let (k',x) = findMax k a m in return ((k',x),delete k' n)++maxElemWithKey E = error $ moduleName++".maxElemWithKey: empty map"+maxElemWithKey (I k a m) = findMax k a m++foldrWithKey f z = foldrWithKeyFM f z . mergeSortFM+foldrWithKey' f z = foldrWithKeyFM' f z . mergeSortFM+foldlWithKey f x = foldlWithKeyFM f x . mergeSortFM+foldlWithKey' f x = foldlWithKeyFM' f x . mergeSortFM+toOrdSeq = toSeq . mergeSortFM+++strict n@E = n+strict n@(I k a m) = strict m `seq` n++strictWith f n@E = n+strictWith f n@(I k a m) = f a `seq` strictWith f m `seq` n+++-- defaults++deleteSeq = deleteSeqUsingFoldr+insertWith = insertWithUsingLookupM+insertSeqWith = insertSeqWithUsingInsertWith+insertWithKey = insertWithKeyUsingInsertWith+insertSeqWithKey = insertSeqWithKeyUsingInsertWithKey+unionWith = unionWithUsingInsertWith+unionSeqWith = unionSeqWithUsingFoldr+fromSeqWith = fromSeqWithUsingInsertSeqWith+fromSeqWithKey = fromSeqWithKeyUsingInsertSeqWithKey+intersectionWith = intersectionWithUsingLookupM+difference = differenceUsingDelete+properSubset = properSubsetUsingSubset+subset = subsetUsingMember+properSubmapBy = properSubmapByUsingSubmapBy+submapBy = submapByUsingLookupM+sameMapBy = sameMapByUsingSubmapBy+properSubmap = A.properSubmap+submap = A.submap+sameMap = A.sameMap+unionWithKey = unionWithKeyUsingInsertWithKey+unionSeqWithKey = unionSeqWithKeyUsingFoldr+intersectionWithKey = intersectionWithKeyUsingLookupM++-- instance declarations++instance Eq k => A.AssocX (FM k) k where+ {empty = empty; singleton = singleton; fromSeq = fromSeq; insert = insert; + insertSeq = insertSeq; union = union; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq; + null = null; size = size; member = member; count = count; + lookup = lookup; lookupM = lookupM; lookupAll = lookupAll; + lookupAndDelete = lookupAndDelete; lookupAndDeleteM = lookupAndDeleteM;+ lookupAndDeleteAll = lookupAndDeleteAll;+ lookupWithDefault = lookupWithDefault; adjust = adjust; + adjustAll = adjustAll; adjustOrInsert = adjustOrInsert;+ adjustAllOrInsert = adjustAllOrInsert;+ adjustOrDelete = adjustOrDelete; adjustOrDeleteAll = adjustOrDeleteAll;+ fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; elements = elements;+ strict = strict; strictWith = strictWith;+ structuralInvariant = structuralInvariant; instanceName m = moduleName}++instance Ord k => A.OrdAssocX (FM k) k where+ {minView = minView; minElem = minElem; deleteMin = deleteMin;+ unsafeInsertMin = unsafeInsertMin; maxView = maxView; maxElem = maxElem;+ deleteMax = deleteMax; unsafeInsertMax = unsafeInsertMax;+ foldr = foldr; foldr' = foldr'; foldl = foldl; foldl' = foldl';+ foldr1 = foldr1; foldr1' = foldr1'; foldl1 = foldl1; foldl1' = foldl1';+ unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend;+ filterLT = filterLT; filterGT = filterGT; filterLE = filterLE;+ filterGE = filterGE; partitionLT_GE = partitionLT_GE;+ partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance Eq k => A.FiniteMapX (FM k) k where+ {fromSeqWith = fromSeqWith; fromSeqWithKey = fromSeqWithKey; + insertWith = insertWith; insertWithKey = insertWithKey; + insertSeqWith = insertSeqWith; insertSeqWithKey = insertSeqWithKey; + unionl = unionl; unionr = unionr; unionWith = unionWith; + unionSeqWith = unionSeqWith; intersectionWith = intersectionWith; + difference = difference; properSubset = properSubset; subset = subset;+ properSubmapBy = properSubmapBy; submapBy = submapBy;+ sameMapBy = sameMapBy}++instance Ord k => A.OrdFiniteMapX (FM k) k++instance Eq k => A.Assoc (FM k) k where+ {toSeq = toSeq; keys = keys; mapWithKey = mapWithKey; + foldWithKey = foldWithKey; foldWithKey' = foldWithKey';+ filterWithKey = filterWithKey; + partitionWithKey = partitionWithKey}++instance Ord k => A.OrdAssoc (FM k) k where+ {minViewWithKey = minViewWithKey; minElemWithKey = minElemWithKey;+ maxViewWithKey = maxViewWithKey; maxElemWithKey = maxElemWithKey;+ foldrWithKey = foldrWithKey; foldrWithKey' = foldrWithKey';+ foldlWithKey = foldlWithKey; foldlWithKey' = foldlWithKey';+ toOrdSeq = toOrdSeq}++instance Eq k => A.FiniteMap (FM k) k where+ {unionWithKey = unionWithKey; unionSeqWithKey = unionSeqWithKey; + intersectionWithKey = intersectionWithKey}++instance Ord k => A.OrdFiniteMap (FM k) k++instance Eq k => Functor (FM k) where+ fmap = map++instance (Eq k,Eq a) => Eq (FM k a) where+ (==) = sameMap++instance (Ord k, Ord a) => Ord (FM k a) where+ compare = compareUsingToOrdList++instance (Eq k,Show k,Show a) => Show (FM k a) where+ showsPrec = showsPrecUsingToList++instance (Eq k,Read k,Read a) => Read (FM k a) where+ readsPrec = readsPrecUsingFromList++instance (Eq k,Arbitrary k,Arbitrary a) => Arbitrary (FM k a) where+ arbitrary = do xs <- arbitrary+ return (Prelude.foldr (uncurry insert) empty xs)++ coarbitrary E = variant 0+ coarbitrary (I k a m) = variant 1 . coarbitrary k+ . coarbitrary a . coarbitrary m+++instance Eq k => Monoid (FM k a) where+ mempty = empty+ mappend = union+ mconcat = unionSeq
+ src/Data/Edison/Assoc/Defaults.hs view
@@ -0,0 +1,313 @@+-- |+-- Module : Data.Edison.Assoc.Defaults+-- Copyright : Copyright (c) 1998 Chris Okasaki+-- License : MIT; see COPYRIGHT file for terms and conditions+--+-- Maintainer : robdockins AT fastmail DOT fm+-- Stability : internal (unstable)+-- Portability : GHC, Hugs (MPTC and FD)+--+-- This module provides default implementations of many of the associative+-- collection operations. These function are used to fill in collection+-- implementations and are not intended to be used directly by end users.++module Data.Edison.Assoc.Defaults where++import Prelude hiding (null,map,lookup,foldr,foldl,foldr1,foldl1,filter)+import Data.Maybe (fromJust)++import Data.Edison.Assoc+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Seq.ListSeq as L+import Data.Edison.Seq.Defaults (tokenMatch,maybeParens)++singletonUsingInsert :: (Assoc m k) => k -> a -> m a+singletonUsingInsert k v = insert k v empty++fromSeqUsingInsertSeq :: (AssocX m k,S.Sequence seq) => seq (k,a) -> m a+fromSeqUsingInsertSeq kvs = insertSeq kvs empty++insertSeqUsingFoldr :: + (AssocX m k,S.Sequence seq) => seq (k,a) -> m a -> m a+insertSeqUsingFoldr kvs m = S.foldr (uncurry insert) m kvs++unionSeqUsingReduce :: (AssocX m k,S.Sequence seq) => seq (m a) -> m a+unionSeqUsingReduce ms = S.reducel union empty ms++deleteSeqUsingFoldr :: (AssocX m k,S.Sequence seq) => seq k -> m a -> m a+deleteSeqUsingFoldr ks m = S.foldr delete m ks++memberUsingLookupM :: (AssocX m k) => k -> m a -> Bool+memberUsingLookupM k m+ = case lookupM k m of+ Just _ -> True+ Nothing -> False++sizeUsingElements :: (AssocX m k) => m a -> Int+sizeUsingElements m = length (elements m)++countUsingMember :: AssocX m k => k -> m a -> Int+countUsingMember k m = if member k m then 1 else 0++lookupAllUsingLookupM :: (AssocX m k,S.Sequence seq) => k -> m a -> seq a+lookupAllUsingLookupM k m = case lookupM k m of+ Just x -> S.singleton x+ Nothing -> S.empty++lookupWithDefaultUsingLookupM :: AssocX m k => a -> k -> m a -> a+lookupWithDefaultUsingLookupM d k m = case lookupM k m of+ Just x -> x+ Nothing -> d++partitionUsingFilter :: AssocX m k => (a -> Bool) -> m a -> (m a,m a)+partitionUsingFilter f m = (filter f m, filter (not . f) m)++fold1UsingElements :: (AssocX m k) => (a -> a -> a) -> m a -> a+fold1UsingElements op m = L.foldr1 op (elements m)++elementsUsingFold :: (AssocX m k,S.Sequence seq) => m a -> seq a+elementsUsingFold = fold S.lcons S.empty++nullUsingElements :: (AssocX m k) => m a -> Bool+nullUsingElements m+ = case elements m of+ [] -> True+ _ -> False++insertWithUsingLookupM :: + FiniteMapX m k => (a -> a -> a) -> k -> a -> m a -> m a+insertWithUsingLookupM f k x m =+ case lookupM k m of+ Nothing -> insert k x m+ Just y -> insert k (f x y) m++fromSeqWithUsingInsertSeqWith ::+ (FiniteMapX m k,S.Sequence seq) => (a -> a -> a) -> seq (k,a) -> m a+fromSeqWithUsingInsertSeqWith f kvs = insertSeqWith f kvs empty++fromSeqWithKeyUsingInsertSeqWithKey :: + (FiniteMapX m k,S.Sequence seq) => (k -> a -> a -> a) -> seq (k,a) -> m a+fromSeqWithKeyUsingInsertSeqWithKey f kvs = insertSeqWithKey f kvs empty++insertWithKeyUsingInsertWith :: + FiniteMapX m k => (k -> a -> a -> a) -> k -> a -> m a -> m a+insertWithKeyUsingInsertWith f k = insertWith (f k) k++insertSeqWithUsingInsertWith :: + (FiniteMapX m k,S.Sequence seq) => + (a -> a -> a) -> seq (k,a) -> m a -> m a+insertSeqWithUsingInsertWith f kvs m =+ S.foldr (uncurry (insertWith f)) m kvs++insertSeqWithKeyUsingInsertWithKey ::+ (FiniteMapX m k,S.Sequence seq) => + (k -> a -> a -> a) -> seq (k,a) -> m a -> m a+insertSeqWithKeyUsingInsertWithKey f kvs m =+ S.foldr (uncurry (insertWithKey f)) m kvs++unionSeqWithUsingReduce :: + (FiniteMapX m k,S.Sequence seq) => (a -> a -> a) -> seq (m a) -> m a+unionSeqWithUsingReduce f ms = S.reducel (unionWith f) empty ms++unionSeqWithUsingFoldr :: + (FiniteMapX m k,S.Sequence seq) => (a -> a -> a) -> seq (m a) -> m a+unionSeqWithUsingFoldr f ms = S.foldr (unionWith f) empty ms++toSeqUsingFoldWithKey :: (Assoc m k,S.Sequence seq) => m a -> seq (k,a)+toSeqUsingFoldWithKey = foldWithKey conspair S.empty+ where conspair k v kvs = S.lcons (k,v) kvs++keysUsingFoldWithKey :: (Assoc m k,S.Sequence seq) => m a -> seq k+keysUsingFoldWithKey = foldWithKey conskey S.empty+ where conskey k v ks = S.lcons k ks++unionWithUsingInsertWith :: + FiniteMap m k => (a -> a -> a) -> m a -> m a -> m a+unionWithUsingInsertWith f m1 m2 = foldWithKey (insertWith f) m2 m1++unionWithKeyUsingInsertWithKey :: + FiniteMap m k => (k -> a -> a -> a) -> m a -> m a -> m a+unionWithKeyUsingInsertWithKey f m1 m2 = foldWithKey (insertWithKey f) m2 m1++unionSeqWithKeyUsingReduce :: + (FiniteMap m k,S.Sequence seq) => + (k -> a -> a -> a) -> seq (m a) -> m a+unionSeqWithKeyUsingReduce f ms = S.reducel (unionWithKey f) empty ms++unionSeqWithKeyUsingFoldr :: + (FiniteMap m k,S.Sequence seq) => + (k -> a -> a -> a) -> seq (m a) -> m a+unionSeqWithKeyUsingFoldr f ms = S.foldr (unionWithKey f) empty ms++intersectionWithUsingLookupM :: + FiniteMap m k => (a -> b -> c) -> m a -> m b -> m c+intersectionWithUsingLookupM f m1 m2 = foldWithKey ins empty m1+ where ins k x m = case lookupM k m2 of+ Nothing -> m+ Just y -> insert k (f x y) m++intersectionWithKeyUsingLookupM :: + FiniteMap m k => (k -> a -> b -> c) -> m a -> m b -> m c+intersectionWithKeyUsingLookupM f m1 m2 = foldWithKey ins empty m1+ where ins k x m = case lookupM k m2 of+ Nothing -> m+ Just y -> insert k (f k x y) m++differenceUsingDelete :: FiniteMap m k => m a -> m b -> m a+differenceUsingDelete m1 m2 = foldWithKey del m1 m2+ where del k _ m = delete k m++properSubsetUsingSubset :: FiniteMapX m k => m a -> m b -> Bool+properSubsetUsingSubset m1 m2 = size m1 < size m2 && subset m1 m2++subsetUsingMember :: FiniteMap m k => m a -> m b -> Bool+subsetUsingMember m1 m2 = foldWithKey mem True m1+ where mem k _ b = member k m2 && b++submapByUsingLookupM :: FiniteMap m k + => (a -> a -> Bool) -> m a -> m a -> Bool+submapByUsingLookupM f m1 m2 = foldWithKey aux True m1+ where aux k x b =+ case lookupM k m2 of+ Nothing -> False+ Just y -> f x y && b++properSubmapByUsingSubmapBy :: FiniteMapX m k + => (a -> a -> Bool) -> m a -> m a -> Bool+properSubmapByUsingSubmapBy f m1 m2 = size m1 < size m2 && submapBy f m1 m2++sameMapByUsingOrdLists :: OrdFiniteMap m k+ => (a -> a -> Bool) -> m a -> m a -> Bool+sameMapByUsingOrdLists f m1 m2 =+ let comp (k1,x1) (k2,x2) = k1 == k2 && f x1 x2+ in L.foldr (&&) (size m1 == size m2) (L.zipWith comp (toOrdList m1) (toOrdList m2))+++sameMapByUsingSubmapBy :: FiniteMapX m k+ => (a -> a -> Bool) -> m a -> m a -> Bool+sameMapByUsingSubmapBy f m1 m2 = size m1 == size m2 && submapBy f m1 m2+++lookupAndDeleteDefault :: AssocX m k => k -> m a -> (a, m a)+lookupAndDeleteDefault k m =+ case lookupM k m of+ Nothing -> error (instanceName m ++ ".lookupAndDelete: lookup failed")+ Just x -> (x, delete k m)++lookupAndDeleteMDefault :: (Monad rm, AssocX m k) => k -> m a -> rm (a, m a)+lookupAndDeleteMDefault k m =+ case lookupM k m of+ Nothing -> fail (instanceName m ++ ".lookupAndDelete: lookup failed")+ Just x -> return (x, delete k m)++lookupAndDeleteAllDefault :: (S.Sequence seq, AssocX m k) => k -> m a -> (seq a,m a)+lookupAndDeleteAllDefault k m = (lookupAll k m,deleteAll k m)++adjustOrInsertUsingMember :: AssocX m k => (a -> a) -> a -> k -> m a -> m a+adjustOrInsertUsingMember f z k m =+ if member k m+ then adjust f k m+ else insert k z m++adjustOrDeleteDefault :: AssocX m k => (a -> Maybe a) -> k -> m a -> m a+adjustOrDeleteDefault f k m =+ case lookupAndDeleteM k m of+ Nothing -> m+ Just (elem,m') ->+ case f elem of+ Nothing -> m'+ Just x -> insert k x m'++adjustOrDeleteAllDefault :: AssocX m k => (a -> Maybe a) -> k -> m a -> m a+adjustOrDeleteAllDefault f k m =+ let (elems,m') = lookupAndDeleteAll k m+ adjSeq = S.map f elems+ ins Nothing m = m+ ins (Just x) m = insert k x m+ in L.foldr ins m' adjSeq++minElemUsingMinView :: OrdAssocX m k => m a -> a+minElemUsingMinView fm =+ case minView fm of+ Nothing -> error $ (instanceName fm)++".minElem: empty map"+ Just (x,_) -> x++deleteMinUsingMinView :: OrdAssocX m k => m a -> m a+deleteMinUsingMinView fm =+ case minView fm of+ Nothing -> error $ (instanceName fm)++".deleteMin: empty map"+ Just (_,m) -> m++minElemWithKeyUsingMinViewWithKey :: OrdAssoc m k => m a -> (k,a)+minElemWithKeyUsingMinViewWithKey fm =+ case minViewWithKey fm of+ Nothing -> error $ (instanceName fm)++".minElemWithKey: empty map"+ Just (x,_) -> x++maxElemUsingMaxView :: OrdAssocX m k => m a -> a+maxElemUsingMaxView fm =+ case maxView fm of+ Nothing -> error $ (instanceName fm)++".maxElem: empty map"+ Just (x,_) -> x++deleteMaxUsingMaxView :: OrdAssocX m k => m a -> m a+deleteMaxUsingMaxView fm =+ case maxView fm of+ Nothing -> error $ (instanceName fm)++".deleteMax: empty map"+ Just (_,m) -> m++maxElemWithKeyUsingMaxViewWithKey :: OrdAssoc m k => m a -> (k,a)+maxElemWithKeyUsingMaxViewWithKey fm =+ case maxViewWithKey fm of+ Nothing -> error $ (instanceName fm)++".maxElemWithKey: empty map"+ Just (x,_) -> x++toOrdSeqUsingFoldrWithKey :: (OrdAssoc m k,S.Sequence seq) => m a -> seq (k,a)+toOrdSeqUsingFoldrWithKey = foldrWithKey (\k x z -> S.lcons (k,x) z) S.empty++showsPrecUsingToList :: (Show k, Show a, Assoc m k) => Int -> m a -> ShowS+showsPrecUsingToList i xs rest+ | i == 0 = concat [ instanceName xs,".fromSeq ",showsPrec 10 (toList xs) rest]+ | otherwise = concat ["(",instanceName xs,".fromSeq ",showsPrec 10 (toList xs) (')':rest)]++readsPrecUsingFromList :: (Read k, Read a, AssocX m k) => Int -> ReadS (m a)+readsPrecUsingFromList i xs =+ let result = maybeParens p xs+ p xs = tokenMatch ((instanceName x)++".fromSeq") xs+ >>= readsPrec 10+ >>= \(l,rest) -> return (fromList l,rest)++ -- play games with the typechecker so we don't have to use+ -- extensions for scoped type variables+ ~[(x,_)] = result++ in result++showsPrecUsingToOrdList :: (Show k,Show a,OrdAssoc m k) => Int -> m a -> ShowS+showsPrecUsingToOrdList i xs rest+ | i == 0 = concat [ instanceName xs,".unsafeFromOrdSeq ",showsPrec 10 (toOrdList xs) rest]+ | otherwise = concat ["(",instanceName xs,".unsafeFromOrdSeq ",showsPrec 10 (toOrdList xs) (')':rest)]++readsPrecUsingUnsafeFromOrdSeq :: (Read k,Read a,OrdAssoc m k) => Int -> ReadS (m a)+readsPrecUsingUnsafeFromOrdSeq i xs =+ let result = maybeParens p xs+ p xs = tokenMatch ((instanceName x)++".unsafeFromOrdSeq") xs+ >>= readsPrec i+ >>= \(l,rest) -> return (unsafeFromOrdList l,rest)++ -- play games with the typechecker so we don't have to use+ -- extensions for scoped type variables+ ~[(x,_)] = result++ in result++compareUsingToOrdList :: (Ord a, OrdAssoc m k) => m a -> m a -> Ordering+compareUsingToOrdList xs ys = cmp (toOrdList xs) (toOrdList ys)+ where+ cmp [] [] = EQ+ cmp [] _ = LT+ cmp _ [] = GT+ cmp (x:xs) (y:ys) =+ case compare x y of+ EQ -> cmp xs ys+ c -> c
+ src/Data/Edison/Assoc/PatriciaLoMap.hs view
@@ -0,0 +1,838 @@+-- |+-- Module : Data.Edison.Assoc.PatriciaLoMap+-- 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)+--+-- Finite maps implemented as little-endian Patricia trees.+--+-- /References:/+--+-- * Chris Okasaki and Any Gill. \"Fast Mergeable Integer Maps\".+-- Workshop on ML, September 1998, pages 77-86.++module Data.Edison.Assoc.PatriciaLoMap (+ -- * Type of little-endian Patricia trees+ FM,++ -- * AssocX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,lookup,lookupM,lookupAll,+ lookupAndDelete,lookupAndDeleteM,lookupAndDeleteAll,strict,strictWith,+ lookupWithDefault,adjust,adjustAll,adjustOrInsert,adjustAllOrInsert,map,+ fold,fold',fold1,fold1',filter,partition,elements,structuralInvariant,++ -- * Assoc operations+ toSeq,keys,mapWithKey,foldWithKey,foldWithKey',filterWithKey,partitionWithKey,++ -- * FiniteMapX operations+ fromSeqWith,fromSeqWithKey,insertWith,insertWithKey,insertSeqWith,+ insertSeqWithKey,unionl,unionr,unionWith,unionSeqWith,intersectionWith,+ difference,properSubset,subset,properSubmapBy,submapBy,sameMapBy,+ properSubmap,submap,sameMap,++ -- * FiniteMap operations+ unionWithKey,unionSeqWithKey,intersectionWithKey,++ -- * OrdAssocX operations+ minView, minElem, deleteMin, unsafeInsertMin,+ maxView, maxElem, deleteMax, unsafeInsertMax,+ foldr, foldr', foldr1, foldr1', foldl, foldl', foldl1, foldl1',+ unsafeFromOrdSeq, unsafeAppend, filterLT, filterLE, filterGT, filterGE,+ partitionLT_GE, partitionLE_GT, partitionLT_GT,++ -- * OrdAssoc operations+ minViewWithKey, minElemWithKey, maxViewWithKey, maxElemWithKey,+ foldrWithKey, foldrWithKey', foldlWithKey, foldlWithKey',+ toOrdSeq,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,map,lookup,foldr,foldl,foldr1,foldl1,filter)+import qualified Prelude+import Control.Monad.Identity (runIdentity)+import Data.Monoid+import Data.Edison.Prelude+import qualified Data.Edison.Assoc as A+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Seq.ListSeq as L+import Data.Edison.Assoc.Defaults+import Data.Int+import Data.Bits+import Test.QuickCheck (Arbitrary(..), variant)++moduleName = "Data.Edison.Assoc.PatriciaLoMap"++data FM a+ = E+ | L Int a+ | B Int Int !(FM a) !(FM a)++-- Invariants:+-- * No B node has an E child+-- * first argument to B is a prefix+-- * second argument to B is the "branching bit" and is+-- always an exact power of two+-- * all bits in the prefix >= the branching bit are zeros+-- * valid prefix bits match all subnodes++structuralInvariant :: FM a -> Bool+structuralInvariant E = True+structuralInvariant (L k x) = True+structuralInvariant x = inv 0 0 x++inv :: Int -> Int -> FM a -> Bool+inv pre msk E = False+inv pre msk (L k x) = k .&. msk == pre+inv pre msk (B p m t0 t1) =+ (p .&. msk == pre) &&+ (bitcount 0 m == 1) &&+ (p .&. (complement (m - 1)) == 0) &&+ inv p0 msk' t0 &&+ inv p1 msk' t1++ where p0 = p+ p1 = p .|. m+ msk' = (m `shiftL` 1) - 1++bitcount :: Int -> Int -> Int+bitcount a 0 = a+bitcount a x = a `seq` bitcount (a+1) (x .&. (x-1))++-- auxiliary functions++makeB p m E t = t+makeB p m t E = t+makeB p m t0 t1 = B p m t0 t1++lmakeB p m E t = t+lmakeB p m t0 t1 = B p m t0 t1++rmakeB p m t E = t+rmakeB p m t0 t1 = B p m t0 t1++lowestBit :: Int32 -> Int32+lowestBit x = x .&. (-x)++branchingBit :: Int -> Int -> Int+branchingBit p0 p1 = + fromIntegral (lowestBit (fromIntegral p0 `xor` fromIntegral p1))++mask :: Int -> Int -> Int+mask p m = fromIntegral (fromIntegral p .&. (fromIntegral m - (1 :: Int32)))++zeroBit :: Int -> Int -> Bool+zeroBit p m = (fromIntegral p) .&. (fromIntegral m) == (0 :: Int32)++matchPrefix :: Int -> Int -> Int -> Bool+matchPrefix k p m = mask k m == p++join p0 t0 p1 t1 =+ let m = branchingBit p0 p1+ in if zeroBit p0 m then B (mask p0 m) m t0 t1+ else B (mask p0 m) m t1 t0++keepR x y = y++-- end auxiliary functions++empty :: FM a+empty = E++singleton :: Int -> a -> FM a+singleton k x = L k x++fromSeq :: S.Sequence seq => seq (Int,a) -> FM a+fromSeq = S.foldl (\t (k, x) -> insert k x t) E++insert :: Int -> a -> FM a -> FM a+insert k x E = L k x+insert k x t@(L j y) = if j == k then L k x else join k (L k x) j t+insert k x t@(B p m t0 t1) =+ if matchPrefix k p m then+ if zeroBit k m then B p m (insert k x t0) t1+ else B p m t0 (insert k x t1)+ else join k (L k x) p t++union :: FM a -> FM a -> FM a+union s@(B p m s0 s1) t@(B q n t0 t1)+ | m < n = if matchPrefix q p m then+ if zeroBit q m then B p m (union s0 t) s1+ else B p m s0 (union s1 t)+ else join p s q t+ | m > n = if matchPrefix p q n then+ if zeroBit p n then B q n (union s t0) t1+ else B q n t0 (union s t1)+ else join p s q t+ | otherwise = if p == q then B p m (union s0 t0) (union s1 t1)+ else join p s q t+union s@(B p m s0 s1) (L k x) =+ if matchPrefix k p m then+ if zeroBit k m then B p m (insert k x s0) s1+ else B p m s0 (insert k x s1)+ else join k (L k x) p s+union s@(B _ _ _ _) E = s+union (L k x) t = insert k x t+union E t = t++delete :: Int -> FM a -> FM a+delete k E = E+delete k t@(L j x) = if k == j then E else t+delete k t@(B p m t0 t1) =+ if matchPrefix k p m then+ if zeroBit k m then lmakeB p m (delete k t0) t1+ else rmakeB p m t0 (delete k t1)+ else t++null :: FM a -> Bool+null E = True+null _ = False++size :: FM a -> Int+size E = 0+size (L _ _) = 1+size (B _ _ t0 t1) = size t0 + size t1++member :: Int -> FM a -> Bool+member k E = False+member k (L j x) = (j == k)+member k (B p m t0 t1) = if zeroBit k m then member k t0 else member k t1++lookup :: Int -> FM a -> a+lookup k m = runIdentity (lookupM k m)++lookupM :: (Monad rm) => Int -> FM a -> rm a+lookupM k E = fail "PatriciaLoMap.lookup: lookup failed"+lookupM k (L j x)+ | j == k = return x+ | otherwise = fail "PatriciaLoMap.lookup: lookup failed"+lookupM k (B p m t0 t1) = if zeroBit k m then lookupM k t0 else lookupM k t1++doLookupAndDelete :: z -> (a -> FM a -> z) -> Int -> FM a -> z+doLookupAndDelete onFail cont k E = onFail+doLookupAndDelete onFail cont k (L j x)+ | j == k = cont x E+ | otherwise = onFail+doLookupAndDelete onFail cont k (B p m t0 t1)+ | zeroBit k m = doLookupAndDelete onFail (\x t0' -> cont x (makeB p m t0' t1)) k t0+ | otherwise = doLookupAndDelete onFail (\x t1' -> cont x (makeB p m t0 t1')) k t1++lookupAndDelete :: Int -> FM a -> (a, FM a)+lookupAndDelete = doLookupAndDelete + (error "PatriciaLoMap.lookupAndDelete: lookup failed") + (,)++lookupAndDeleteM :: Monad m => Int -> FM a -> m (a, FM a)+lookupAndDeleteM = doLookupAndDelete + (fail "PatriciaLoMap.lookupAndDelete: lookup failed")+ (\x m -> return (x,m))++lookupAndDeleteAll :: S.Sequence seq => Int -> FM a -> (seq a,FM a)+lookupAndDeleteAll k m = doLookupAndDelete+ (S.empty, m)+ (\x m' -> (S.singleton x,m'))+ k m+++adjust :: (a -> a) -> Int -> FM a -> FM a+adjust f k E = E+adjust f k t@(L j x) = if k == j then L k (f x) else t+adjust f k t@(B p m t0 t1) =+ if matchPrefix k p m then+ if zeroBit k m then B p m (adjust f k t0) t1+ else B p m t0 (adjust f k t1)+ else t++-- FIXME can we do better than this?+adjustOrInsert :: (a -> a) -> a -> Int -> FM a -> FM a+adjustOrInsert = adjustOrInsertUsingMember++adjustAllOrInsert :: (a -> a) -> a -> Int -> FM a -> FM a+adjustAllOrInsert = adjustOrInsertUsingMember++adjustOrDelete :: (a -> Maybe a) -> Int -> FM a -> FM a+adjustOrDelete = adjustOrDeleteDefault++adjustOrDeleteAll :: (a -> Maybe a) -> Int -> FM a -> FM a+adjustOrDeleteAll = adjustOrDeleteDefault++map :: (a -> b) -> FM a -> FM b+map f E = E+map f (L k x) = L k (f x)+map f (B p m t0 t1) = B p m (map f t0) (map f t1)++fold :: (a -> b -> b) -> b -> FM a -> b+fold f c E = c+fold f c (L k x) = f x c+fold f c (B p m t0 t1) = fold f (fold f c t1) t0++fold' :: (a -> b -> b) -> b -> FM a -> b+fold' f c E = c+fold' f c (L k x) = c `seq` f x c+fold' f c (B p m t0 t1) = c `seq` (fold f $! (fold f c t1)) t0++fold1 :: (a -> a -> a) -> FM a -> a+fold1 f E = error "PatriciaLoMap.fold1: empty map"+fold1 f (L k x) = x+fold1 f (B p m t0 t1) = f (fold1 f t0) (fold1 f t1)++fold1' :: (a -> a -> a) -> FM a -> a+fold1' f E = error "PatriciaLoMap.fold1: empty map"+fold1' f (L k x) = x+fold1' f (B p m t0 t1) = f (fold1' f t0) $! (fold1' f t1)++filter :: (a -> Bool) -> FM a -> FM a+filter g E = E+filter g t@(L k x) = if g x then t else E+filter g (B p m t0 t1) = makeB p m (filter g t0) (filter g t1)++partition :: (a -> Bool) -> FM a -> (FM a, FM a)+partition g E = (E, E)+partition g t@(L k x) = if g x then (t, E) else (E, t)+partition g (B p m t0 t1) =+ let (t0',t0'') = partition g t0+ (t1',t1'') = partition g t1+ in (makeB p m t0' t1', makeB p m t0'' t1'')+ +fromSeqWith :: S.Sequence seq => (a -> a -> a) -> seq (Int,a) -> FM a+fromSeqWith f = S.foldl (\t (k, x) -> insertWith f k x t) E++insertWith :: (a -> a -> a) -> Int -> a -> FM a -> FM a+insertWith f k x E = L k x+insertWith f k x t@(L j y) = if j == k then L k (f x y) else join k (L k x) j t+insertWith f k x t@(B p m t0 t1) =+ if matchPrefix k p m then+ if zeroBit k m then B p m (insertWith f k x t0) t1+ else B p m t0 (insertWith f k x t1)+ else join k (L k x) p t++unionl :: FM a -> FM a -> FM a+unionl s@(B p m s0 s1) t@(B q n t0 t1)+ | m < n = if matchPrefix q p m then+ if zeroBit q m then B p m (unionl s0 t) s1+ else B p m s0 (unionl s1 t)+ else join p s q t+ | m > n = if matchPrefix p q n then+ if zeroBit p n then B q n (unionl s t0) t1+ else B q n t0 (unionl s t1)+ else join p s q t+ | otherwise = if p == q then B p m (unionl s0 t0) (unionl s1 t1)+ else join p s q t+unionl s@(B p m s0 s1) (L k x) =+ if matchPrefix k p m then+ if zeroBit k m then B p m (insertWith keepR k x s0) s1+ else B p m s0 (insertWith keepR k x s1)+ else join k (L k x) p s+unionl s@(B _ _ _ _) E = s+unionl (L k x) t = insert k x t+unionl E t = t++unionr :: FM a -> FM a -> FM a+unionr s@(B p m s0 s1) t@(B q n t0 t1)+ | m < n = if matchPrefix q p m then+ if zeroBit q m then B p m (unionr s0 t) s1+ else B p m s0 (unionr s1 t)+ else join p s q t+ | m > n = if matchPrefix p q n then+ if zeroBit p n then B q n (unionr s t0) t1+ else B q n t0 (unionr s t1)+ else join p s q t+ | otherwise = if p == q then B p m (unionr s0 t0) (unionr s1 t1)+ else join p s q t+unionr s@(B p m s0 s1) (L k x) =+ if matchPrefix k p m then+ if zeroBit k m then B p m (insert k x s0) s1+ else B p m s0 (insert k x s1)+ else join k (L k x) p s+unionr s@(B _ _ _ _) E = s+unionr (L k x) t = insertWith keepR k x t+unionr E t = t++unionWith :: (a -> a -> a) -> FM a -> FM a -> FM a+unionWith f s@(B p m s0 s1) t@(B q n t0 t1)+ | m < n = if matchPrefix q p m then+ if zeroBit q m then B p m (unionWith f s0 t) s1+ else B p m s0 (unionWith f s1 t)+ else join p s q t+ | m > n = if matchPrefix p q n then+ if zeroBit p n then B q n (unionWith f s t0) t1+ else B q n t0 (unionWith f s t1)+ else join p s q t+ | otherwise = if p == q then B p m (unionWith f s0 t0) (unionWith f s1 t1)+ else join p s q t+unionWith f s@(B p m s0 s1) (L k x) =+ if matchPrefix k p m then+ if zeroBit k m then B p m (insertWith (flip f) k x s0) s1+ else B p m s0 (insertWith (flip f) k x s1)+ else join k (L k x) p s+unionWith f s@(B _ _ _ _) E = s+unionWith f (L k x) t = insertWith f k x t+unionWith f E t = t++intersectionWith :: (a -> b -> c) -> FM a -> FM b -> FM c+intersectionWith f s@(B p m s0 s1) t@(B q n t0 t1)+ | m < n = if matchPrefix q p m then+ if zeroBit q m then intersectionWith f s0 t+ else intersectionWith f s1 t+ else E+ | m > n = if matchPrefix p q n then+ if zeroBit p n then intersectionWith f s t0+ else intersectionWith f s t1+ else E+ | otherwise = if p /= q then E+ else makeB p m (intersectionWith f s0 t0) (intersectionWith f s1 t1)+intersectionWith f (B p m s0 s1) (L k y) =+ case lookupM k (if zeroBit k m then s0 else s1) of+ Just x -> L k (f x y)+ Nothing -> E+intersectionWith f s@(B _ _ _ _) E = E+intersectionWith f (L k x) t =+ case lookupM k t of+ Just y -> L k (f x y)+ Nothing -> E+intersectionWith f E t = E++difference :: FM a -> FM b -> FM a+difference s@(B p m s0 s1) t@(B q n t0 t1)+ | m < n = if matchPrefix q p m then+ if zeroBit q m then lmakeB p m (difference s0 t) s1+ else rmakeB p m s0 (difference s1 t)+ else s+ | m > n = if matchPrefix p q n then+ if zeroBit p n then difference s t0+ else difference s t1+ else s+ | otherwise = if p /= q then s+ else makeB p m (difference s0 t0) (difference s1 t1)+difference s@(B p m s0 s1) (L k y) =+ if matchPrefix k p m then+ if zeroBit k m then lmakeB p m (delete k s0) s1+ else rmakeB p m s0 (delete k s1)+ else s+difference s@(B _ _ _ _) E = s+difference s@(L k x) t = if member k t then E else s+difference E t = E++properSubset :: FM a -> FM b -> Bool+properSubset s t = case subset' s t of {LT -> True; _ -> False}++subset' s@(B p m s0 s1) t@(B q n t0 t1)+ | m < n = GT+ | m > n = if matchPrefix p q n then+ if zeroBit p n then subset' s t0+ else subset' s t1+ else GT+ | otherwise = if p == q then case (subset' s0 t0,subset' s1 t1) of+ (GT,_) -> GT+ (_,GT) -> GT+ (EQ,EQ) -> EQ+ (_,_) -> LT+ else GT+subset' (B p m s0 s1) _ = GT+subset' (L k x) (L j y) = if k == j then EQ else GT+subset' (L k x) t = if member k t then LT else GT+subset' E E = EQ+subset' E _ = LT++subset :: FM a -> FM b -> Bool+subset s@(B p m s0 s1) t@(B q n t0 t1)+ | m < n = False+ | m > n = matchPrefix p q n && (if zeroBit p n then subset s t0+ else subset s t1)+ | otherwise = (p == q) && subset s0 t0 && subset s1 t1+subset (B p m s0 s1) _ = False+subset (L k x) t = member k t+subset E t = True++properSubmapBy :: (a -> a -> Bool) -> FM a -> FM a -> Bool+properSubmapBy = properSubmapByUsingSubmapBy++submapBy :: (a -> a -> Bool) -> FM a -> FM a -> Bool+submapBy = submapByUsingLookupM++sameMapBy :: (a -> a -> Bool) -> FM a -> FM a -> Bool+sameMapBy = sameMapByUsingSubmapBy++properSubmap :: (Eq a) => FM a -> FM a -> Bool+properSubmap = A.properSubmap++submap :: (Eq a) => FM a -> FM a -> Bool+submap = A.submap++sameMap :: (Eq a) => FM a -> FM a -> Bool+sameMap = A.sameMap++mapWithKey :: (Int -> a -> b) -> FM a -> FM b+mapWithKey f E = E+mapWithKey f (L k x) = L k (f k x)+mapWithKey f (B p m t0 t1) = B p m (mapWithKey f t0) (mapWithKey f t1)++foldWithKey :: (Int -> a -> b -> b) -> b -> FM a -> b+foldWithKey f c E = c+foldWithKey f c (L k x) = f k x c+foldWithKey f c (B p m t0 t1) = foldWithKey f (foldWithKey f c t1) t0++foldWithKey' :: (Int -> a -> b -> b) -> b -> FM a -> b+foldWithKey' f c E = c+foldWithKey' f c (L k x) = c `seq` f k x c+foldWithKey' f c (B p m t0 t1) = c `seq` (foldWithKey f $! (foldWithKey f c t1)) t0+++filterWithKey :: (Int -> a -> Bool) -> FM a -> FM a+filterWithKey g E = E+filterWithKey g t@(L k x) = if g k x then t else E+filterWithKey g (B p m t0 t1) = + makeB p m (filterWithKey g t0) (filterWithKey g t1)++partitionWithKey :: (Int -> a -> Bool) -> FM a -> (FM a, FM a)+partitionWithKey g E = (E, E)+partitionWithKey g t@(L k x) = if g k x then (t, E) else (E, t)+partitionWithKey g (B p m t0 t1) =+ let (t0',t0'') = partitionWithKey g t0+ (t1',t1'') = partitionWithKey g t1+ in (makeB p m t0' t1', makeB p m t0'' t1'')++unionWithKey :: (Int -> a -> a -> a) -> FM a -> FM a -> FM a+unionWithKey f s@(B p m s0 s1) t@(B q n t0 t1)+ | m < n = if matchPrefix q p m then+ if zeroBit q m then B p m (unionWithKey f s0 t) s1+ else B p m s0 (unionWithKey f s1 t)+ else join p s q t+ | m > n = if matchPrefix p q n then+ if zeroBit p n then B q n (unionWithKey f s t0) t1+ else B q n t0 (unionWithKey f s t1)+ else join p s q t+ | otherwise = if p == q then B p m (unionWithKey f s0 t0) (unionWithKey f s1 t1)+ else join p s q t+unionWithKey f s@(B p m s0 s1) (L k x) =+ if matchPrefix k p m then+ if zeroBit k m then B p m (insertWith (flip (f k)) k x s0) s1+ else B p m s0 (insertWith (flip (f k)) k x s1)+ else join k (L k x) p s+unionWithKey f s@(B _ _ _ _) E = s+unionWithKey f (L k x) t = insertWith (f k) k x t+unionWithKey f E t = t++intersectionWithKey :: (Int -> a -> b -> c) -> FM a -> FM b -> FM c+intersectionWithKey f s@(B p m s0 s1) t@(B q n t0 t1)+ | m < n = if matchPrefix q p m then+ if zeroBit q m then intersectionWithKey f s0 t+ else intersectionWithKey f s1 t+ else E+ | m > n = if matchPrefix p q n then+ if zeroBit p n then intersectionWithKey f s t0+ else intersectionWithKey f s t1+ else E+ | otherwise = if p /= q then E+ else makeB p m (intersectionWithKey f s0 t0) (intersectionWithKey f s1 t1)+intersectionWithKey f (B p m s0 s1) (L k y) =+ case lookupM k (if zeroBit k m then s0 else s1) of+ Just x -> L k (f k x y)+ Nothing -> E+intersectionWithKey f s@(B _ _ _ _) E = E+intersectionWithKey f (L k x) t =+ case lookupM k t of+ Just y -> L k (f k x y)+ Nothing -> E+intersectionWithKey f E t = E++-- Datastructure definition is strict in all submaps,+-- no forcing required+strict n = n++strictWith f n@E = n+strictWith f n@(L i x) = f x `seq` n+strictWith f n@(B i j m1 m2) = strictWith f m1 `seq` strictWith f m2 `seq` n+++ordListFM :: FM a -> [(Int,a)]+ordListFM E = []+ordListFM (L k x) = [(k,x)]+ordListFM (B p m t0 t1) = merge (ordListFM t0) (ordListFM t1)+ where merge [] ys = ys+ merge xs [] = xs+ merge (x@(k1,_):xs) (y@(k2,_):ys) =+ case compare k1 k2 of+ LT -> x : merge xs (y:ys)+ GT -> y : merge (x:xs) ys+ EQ -> error "PatriciaLoMap: bug in ordListFM"++ordListFM_rev :: FM a -> [(Int,a)]+ordListFM_rev E = []+ordListFM_rev (L k x) = [(k,x)]+ordListFM_rev (B p m t0 t1) = merge (ordListFM_rev t0) (ordListFM_rev t1)+ where merge [] ys = ys+ merge xs [] = xs+ merge (x@(k1,_):xs) (y@(k2,_):ys) =+ case compare k1 k2 of+ LT -> y : merge (x:xs) ys+ GT -> x : merge xs (y:ys)+ EQ -> error "PatriciaLoMap: bug in ordListFM_rev"++minView :: Monad m => FM a -> m (a, FM a)+minView fm = + case ordListFM fm of+ [] -> fail $ moduleName++".minView: empty map"+ ((k,x):_) -> return (x,delete k fm)++minViewWithKey :: Monad m => FM a -> m ((Int, a), FM a)+minViewWithKey fm =+ case ordListFM fm of+ [] -> fail $ moduleName++".minViewWithKey: empty map"+ ((k,x):_) -> return ((k,x),delete k fm)++maxView :: Monad m => FM a -> m (a, FM a)+maxView fm =+ case ordListFM_rev fm of+ [] -> fail $ moduleName++".maxView: empty map"+ ((k,x):_) -> return (x,delete k fm)++maxViewWithKey :: Monad m => FM a -> m ((Int, a), FM a)+maxViewWithKey fm =+ case ordListFM_rev fm of+ [] -> fail $ moduleName++".maxViewWithKey: empty map"+ ((k,x):_) -> return ((k,x),delete k fm)++minElem :: FM a -> a+minElem = minElemUsingMinView++minElemWithKey :: FM a -> (Int,a)+minElemWithKey = minElemWithKeyUsingMinViewWithKey++deleteMin :: FM a -> FM a+deleteMin = deleteMinUsingMinView++unsafeInsertMin :: Int -> a -> FM a -> FM a+unsafeInsertMin = insert++maxElem :: FM a -> a+maxElem = maxElemUsingMaxView++deleteMax :: FM a -> FM a+deleteMax = deleteMaxUsingMaxView++maxElemWithKey :: FM a -> (Int,a)+maxElemWithKey = maxElemWithKeyUsingMaxViewWithKey++unsafeInsertMax :: Int -> a -> FM a -> FM a+unsafeInsertMax = insert++foldr :: (a -> b -> b) -> b -> FM a -> b+foldr f z fm = L.foldr f z . L.map snd . ordListFM $ fm++foldr' :: (a -> b -> b) -> b -> FM a -> b+foldr' f z fm = L.foldl' (flip f) z . L.map snd . ordListFM_rev $ fm++foldr1 :: (a -> a -> a) -> FM a -> a+foldr1 f fm = L.foldr1 f . L.map snd . ordListFM $ fm++foldr1' :: (a -> a -> a) -> FM a -> a+foldr1' f fm = L.foldl1' (flip f) . L.map snd . ordListFM_rev $ fm++foldl :: (b -> a -> b) -> b -> FM a -> b+foldl f z fm = L.foldr (flip f) z . L.map snd . ordListFM_rev $ fm++foldl' :: (b -> a -> b) -> b -> FM a -> b+foldl' f z fm = L.foldl' f z . L.map snd . ordListFM $ fm++foldl1 :: (a -> a -> a) -> FM a -> a+foldl1 f fm = L.foldr1 (flip f) . L.map snd . ordListFM_rev $ fm++foldl1' :: (a -> a -> a) -> FM a -> a+foldl1' f fm = L.foldl1' f . L.map snd . ordListFM $ fm++foldrWithKey :: (Int -> a -> b -> b) -> b -> FM a -> b+foldrWithKey f z fm = L.foldr (uncurry f) z . ordListFM $ fm++foldrWithKey' :: (Int -> a -> b -> b) -> b -> FM a -> b+foldrWithKey' f z fm = L.foldl' (flip (uncurry f)) z . ordListFM_rev $ fm++foldlWithKey :: (b -> Int -> a -> b) -> b -> FM a -> b+foldlWithKey f z fm = L.foldr (\ (k,x) z -> f z k x) z . ordListFM_rev $ fm++foldlWithKey' :: (b -> Int -> a -> b) -> b -> FM a -> b+foldlWithKey' f z fm = L.foldl' (\ z (k,x) -> f z k x) z . ordListFM $ fm+++unsafeFromOrdSeq :: S.Sequence seq => seq (Int,a) -> FM a+unsafeFromOrdSeq = fromSeq++unsafeAppend :: FM a -> FM a -> FM a+unsafeAppend = union++filterLT :: Int -> FM a -> FM a+filterLT k = filterWithKey (\k' _ -> k' < k)++filterLE :: Int -> FM a -> FM a+filterLE k = filterWithKey (\k' _ -> k' <= k)++filterGT :: Int -> FM a -> FM a+filterGT k = filterWithKey (\k' _ -> k' > k)++filterGE :: Int -> FM a -> FM a+filterGE k = filterWithKey (\k' _ -> k' >= k)++partitionLT_GE :: Int -> FM a -> (FM a, FM a)+partitionLT_GE k fm = (filterLT k fm,filterGE k fm)++partitionLE_GT :: Int -> FM a -> (FM a,FM a)+partitionLE_GT k fm = (filterLE k fm,filterGT k fm)++partitionLT_GT :: Int -> FM a -> (FM a,FM a)+partitionLT_GT k fm = (filterLT k fm,filterGT k fm)++toOrdSeq :: S.Sequence seq => FM a -> seq (Int,a)+toOrdSeq = L.foldr S.lcons S.empty . ordListFM++-- defaults++insertSeq :: S.Sequence seq => seq (Int,a) -> FM a -> FM a+insertSeq = insertSeqUsingFoldr++unionSeq :: S.Sequence seq => seq (FM a) -> FM a+unionSeq = unionSeqUsingReduce++deleteAll :: Int -> FM a -> FM a+deleteAll = delete++deleteSeq :: S.Sequence seq => seq Int -> FM a -> FM a+deleteSeq = deleteSeqUsingFoldr++count :: Int -> FM a -> Int+count = countUsingMember++lookupAll :: S.Sequence seq => Int -> FM a -> seq a+lookupAll = lookupAllUsingLookupM++lookupWithDefault :: a -> Int -> FM a -> a+lookupWithDefault = lookupWithDefaultUsingLookupM++elements :: S.Sequence seq => FM a -> seq a+elements = elementsUsingFold++fromSeqWithKey :: + S.Sequence seq => (Int -> a -> a -> a) -> seq (Int,a) -> FM a+fromSeqWithKey = fromSeqWithKeyUsingInsertSeqWithKey++insertWithKey :: (Int -> a -> a -> a) -> Int -> a -> FM a -> FM a+insertWithKey = insertWithKeyUsingInsertWith++insertSeqWith :: + S.Sequence seq => (a -> a -> a) -> seq (Int,a) -> FM a -> FM a+insertSeqWith = insertSeqWithUsingInsertWith++insertSeqWithKey :: + S.Sequence seq => + (Int -> a -> a -> a) -> seq (Int,a) -> FM a -> FM a+insertSeqWithKey = insertSeqWithKeyUsingInsertWithKey++adjustAll :: (a -> a) -> Int -> FM a -> FM a+adjustAll = adjust++unionSeqWith :: S.Sequence seq => (a -> a -> a) -> seq (FM a) -> FM a+unionSeqWith = unionSeqWithUsingReduce++toSeq :: S.Sequence seq => FM a -> seq (Int,a)+toSeq = toSeqUsingFoldWithKey++keys :: S.Sequence seq => FM a -> seq Int+keys = keysUsingFoldWithKey+ +unionSeqWithKey :: + S.Sequence seq => (Int -> a -> a -> a) -> seq (FM a) -> FM a+unionSeqWithKey = unionSeqWithKeyUsingReduce++-- instance declarations++instance A.AssocX FM Int where+ {empty = empty; singleton = singleton; fromSeq = fromSeq; insert = insert; + insertSeq = insertSeq; union = union; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq; + null = null; size = size; member = member; count = count; + lookup = lookup; lookupM = lookupM; lookupAll = lookupAll;+ lookupAndDelete = lookupAndDelete; lookupAndDeleteM = lookupAndDeleteM;+ lookupAndDeleteAll = lookupAndDeleteAll;+ lookupWithDefault = lookupWithDefault; adjust = adjust;+ adjustAll = adjustAll; adjustOrInsert = adjustOrInsert;+ adjustAllOrInsert = adjustAllOrInsert;+ adjustOrDelete = adjustOrDelete; adjustOrDeleteAll = adjustOrDeleteAll;+ fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; elements = elements;+ strict = strict; strictWith = strictWith;+ structuralInvariant = structuralInvariant; instanceName m = moduleName}++instance A.Assoc FM Int where+ {toSeq = toSeq; keys = keys; mapWithKey = mapWithKey; + foldWithKey = foldWithKey; foldWithKey' = foldWithKey';+ filterWithKey = filterWithKey; + partitionWithKey = partitionWithKey}++instance A.FiniteMapX FM Int where+ {fromSeqWith = fromSeqWith; fromSeqWithKey = fromSeqWithKey; + insertWith = insertWith; insertWithKey = insertWithKey; + insertSeqWith = insertSeqWith; insertSeqWithKey = insertSeqWithKey; + unionl = unionl; unionr = unionr; unionWith = unionWith; + unionSeqWith = unionSeqWith; intersectionWith = intersectionWith; + difference = difference; properSubset = properSubset; subset = subset;+ properSubmapBy = properSubmapBy; submapBy = submapBy;+ sameMapBy = sameMapBy}++instance A.FiniteMap FM Int where+ {unionWithKey = unionWithKey; unionSeqWithKey = unionSeqWithKey; + intersectionWithKey = intersectionWithKey}++instance A.OrdAssocX FM Int where+ {minView = minView; minElem = minElem; deleteMin = deleteMin;+ unsafeInsertMin = unsafeInsertMin; maxView = maxView; maxElem = maxElem;+ deleteMax = deleteMax; unsafeInsertMax = unsafeInsertMax;+ foldr = foldr; foldr' = foldr'; foldl = foldl; foldl' = foldl';+ foldr1 = foldr1; foldr1' = foldr1'; foldl1 = foldl1; foldl1' = foldl1';+ unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend;+ filterLT = filterLT; filterGT = filterGT; filterLE = filterLE;+ filterGE = filterGE; partitionLT_GE = partitionLT_GE;+ partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance A.OrdAssoc FM Int where+ {minViewWithKey = minViewWithKey; minElemWithKey = minElemWithKey;+ maxViewWithKey = maxViewWithKey; maxElemWithKey = maxElemWithKey;+ foldrWithKey = foldrWithKey; foldrWithKey' = foldrWithKey';+ foldlWithKey = foldlWithKey; foldlWithKey' = foldlWithKey';+ toOrdSeq = toOrdSeq}++instance A.OrdFiniteMapX FM Int+instance A.OrdFiniteMap FM Int++instance Functor FM where+ fmap = map++instance (Show a) => Show (FM a) where+ showsPrec = showsPrecUsingToList++instance (Read a) => Read (FM a) where+ readsPrec = readsPrecUsingFromList++instance (Eq a) => Eq (FM a) where+ (==) = sameMap++instance (Ord a) => Ord (FM a) where+ compare = compareUsingToOrdList++instance (Arbitrary a) => Arbitrary (FM a) where+ arbitrary = do xs <- arbitrary+ return (Prelude.foldr (uncurry insert) empty xs)++ coarbitrary E = variant 0+ coarbitrary (L i a) = variant 1 . coarbitrary i . coarbitrary a+ coarbitrary (B i j m n) = variant 2 . coarbitrary i . coarbitrary j+ . coarbitrary m . coarbitrary n+++instance Monoid (FM a) where+ mempty = empty+ mappend = union+ mconcat = unionSeq
+ src/Data/Edison/Assoc/StandardMap.hs view
@@ -0,0 +1,372 @@+-- |+-- Module : Data.Edison.Assoc.AssocList+-- 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)+--+-- The standard library "Data.Map" repackaged as an Edison+-- associative collection.++module Data.Edison.Assoc.StandardMap (+ -- * Type of standard finite maps+ FM,++ -- * AssocX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,lookup,lookupM,lookupAll,+ lookupAndDelete,lookupAndDeleteM,lookupAndDeleteAll,+ lookupWithDefault,adjust,adjustAll,adjustOrInsert,adjustAllOrInsert,+ adjustOrDelete,adjustOrDeleteAll,strict,strictWith,+ map,fold,fold',fold1,fold1',filter,partition,elements,structuralInvariant,++ -- * FiniteMapX operations+ fromSeqWith,fromSeqWithKey,insertWith,insertWithKey,insertSeqWith,+ insertSeqWithKey,unionl,unionr,unionWith,unionSeqWith,intersectionWith,+ difference,properSubset,subset,properSubmapBy,submapBy,sameMapBy,+ properSubmap,submap,sameMap,++ -- * OrdAssocX operations+ minView, minElem, deleteMin, unsafeInsertMin, maxView, maxElem, deleteMax,+ unsafeInsertMax, foldr, foldr', foldl, foldl', foldr1, foldr1',+ foldl1, foldl1', unsafeFromOrdSeq,+ unsafeAppend, filterLT, filterLE, filterGT, filterGE,+ partitionLT_GE, partitionLE_GT, partitionLT_GT,++ -- * Assoc operations+ toSeq,keys,mapWithKey,foldWithKey,foldWithKey',filterWithKey,partitionWithKey,++ -- * OrdAssoc operations+ minViewWithKey, minElemWithKey, maxViewWithKey, maxElemWithKey,+ foldrWithKey, foldrWithKey', foldlWithKey, foldlWithKey', toOrdSeq,++ -- * FiniteMap operations+ unionWithKey,unionSeqWithKey,intersectionWithKey,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,map,lookup,foldr,foldl,foldr1,foldl1,filter)+import qualified Prelude+import Control.Monad.Identity (runIdentity)+import Data.Edison.Prelude+import qualified Data.Edison.Assoc as A+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Seq.ListSeq as L+import Data.Edison.Assoc.Defaults+import Data.Int+import Data.Bits+import Test.QuickCheck (Arbitrary(..))++import qualified Data.Map as DM++type FM = DM.Map++moduleName :: String+moduleName = "Data.Edison.Assoc.StandardMap"++empty :: FM k a+singleton :: Ord k => k -> a -> FM k a+fromSeq :: (Ord k,S.Sequence seq) => seq (k,a) -> FM k a+insert :: Ord k => k -> a -> FM k a -> FM k a+insertSeq :: (Ord k,S.Sequence seq) => seq (k,a) -> FM k a -> FM k a+union :: Ord k => FM k a -> FM k a -> FM k a+unionSeq :: (Ord k,S.Sequence seq) => seq (FM k a) -> FM k a+delete :: Ord k => k -> FM k a -> FM k a+deleteAll :: Ord k => k -> FM k a -> FM k a+deleteSeq :: (Ord k,S.Sequence seq) => seq k -> FM k a -> FM k a+null :: FM k a -> Bool+size :: FM k a -> Int+member :: Ord k => k -> FM k a -> Bool+count :: Ord k => k -> FM k a -> Int+lookup :: Ord k => k -> FM k a -> a+lookupAll :: (Ord k,S.Sequence seq) => k -> FM k a -> seq a+lookupM :: (Ord k,Monad m) => k -> FM k a -> m a+lookupWithDefault :: Ord k => a -> k -> FM k a -> a+lookupAndDelete :: Ord k => k -> FM k a -> (a, FM k a)+lookupAndDeleteM :: (Ord k,Monad m) => k -> FM k a -> m (a, FM k a)+lookupAndDeleteAll :: (Ord k,S.Sequence seq) => k -> FM k a -> (seq a,FM k a)+adjust :: Ord k => (a->a) -> k -> FM k a -> FM k a+adjustAll :: Ord k => (a->a) -> k -> FM k a -> FM k a+adjustOrInsert :: Ord k => (a -> a) -> a -> k -> FM k a -> FM k a+adjustAllOrInsert :: Ord k => (a -> a) -> a -> k -> FM k a -> FM k a+adjustOrDelete :: Ord k => (a -> Maybe a) -> k -> FM k a -> FM k a+adjustOrDeleteAll :: Ord k => (a -> Maybe a) -> k -> FM k a -> FM k a+strict :: Ord k => FM k a -> FM k a+strictWith :: Ord k => (a -> b) -> FM k a -> FM k a+map :: (Ord k,Functor (FM k)) => (a -> b) -> FM k a -> FM k b+fold :: Ord k => (a -> b -> b) -> b -> FM k a -> b+fold1 :: Ord k => (a -> a -> a) -> FM k a -> a+fold' :: Ord k => (a -> b -> b) -> b -> FM k a -> b+fold1' :: Ord k => (a -> a -> a) -> FM k a -> a+filter :: Ord k => (a -> Bool) -> FM k a -> FM k a+partition :: Ord k => (a -> Bool) -> FM k a -> (FM k a,FM k a)+elements :: (Ord k,S.Sequence seq) => FM k a -> seq a++minView :: (Ord k,Monad m) => FM k a -> m (a, FM k a)+minElem :: Ord k => FM k a -> a+deleteMin :: Ord k => FM k a -> FM k a+unsafeInsertMin :: Ord k => k -> a -> FM k a -> FM k a+maxView :: (Ord k,Monad m) => FM k a -> m (a, FM k a)+maxElem :: Ord k => FM k a -> a+deleteMax :: Ord k => FM k a -> FM k a+unsafeInsertMax :: Ord k => k -> a -> FM k a -> FM k a+foldr :: Ord k => (a -> b -> b) -> b -> FM k a -> b+foldl :: Ord k => (b -> a -> b) -> b -> FM k a -> b+foldr1 :: Ord k => (a -> a -> a) -> FM k a -> a+foldl1 :: Ord k => (a -> a -> a) -> FM k a -> a+foldr' :: Ord k => (a -> b -> b) -> b -> FM k a -> b+foldl' :: Ord k => (b -> a -> b) -> b -> FM k a -> b+foldr1' :: Ord k => (a -> a -> a) -> FM k a -> a+foldl1' :: Ord k => (a -> a -> a) -> FM k a -> a+unsafeFromOrdSeq :: (Ord k,S.Sequence seq) => seq (k,a) -> FM k a+unsafeAppend :: Ord k => FM k a -> FM k a -> FM k a+filterLT :: Ord k => k -> FM k a -> FM k a+filterGT :: Ord k => k -> FM k a -> FM k a+filterLE :: Ord k => k -> FM k a -> FM k a+filterGE :: Ord k => k -> FM k a -> FM k a+partitionLT_GE :: Ord k => k -> FM k a -> (FM k a,FM k a)+partitionLE_GT :: Ord k => k -> FM k a -> (FM k a,FM k a)+partitionLT_GT :: Ord k => k -> FM k a -> (FM k a,FM k a)++fromSeqWith :: (Ord k,S.Sequence seq) => (a -> a -> a) + -> seq (k,a) -> FM k a+fromSeqWithKey :: (Ord k,S.Sequence seq) => (k -> a -> a -> a)+ -> seq (k,a) -> FM k a+insertWith :: Ord k => (a -> a -> a) -> k -> a+ -> FM k a -> FM k a+insertWithKey :: Ord k => (k -> a -> a -> a) -> k -> a+ -> FM k a -> FM k a+insertSeqWith :: (Ord k,S.Sequence seq) => (a -> a -> a) -> seq (k,a)+ -> FM k a -> FM k a+insertSeqWithKey :: (Ord k,S.Sequence seq) => (k -> a -> a -> a) -> seq (k,a)+ -> FM k a -> FM k a+unionl :: Ord k => FM k a -> FM k a -> FM k a+unionr :: Ord k => FM k a -> FM k a -> FM k a+unionWith :: Ord k => (a -> a -> a) -> FM k a -> FM k a -> FM k a+unionSeqWith :: (Ord k,S.Sequence seq) =>+ (a -> a -> a) -> seq (FM k a) -> FM k a+intersectionWith :: Ord k => (a -> b -> c) -> FM k a -> FM k b -> FM k c+difference :: Ord k => FM k a -> FM k b -> FM k a+properSubset :: Ord k => FM k a -> FM k b -> Bool+subset :: Ord k => FM k a -> FM k b -> Bool+properSubmapBy :: Ord k => (a -> a -> Bool) -> FM k a -> FM k a -> Bool+submapBy :: Ord k => (a -> a -> Bool) -> FM k a -> FM k a -> Bool+sameMapBy :: Ord k => (a -> a -> Bool) -> FM k a -> FM k a -> Bool+properSubmap :: (Ord k,Eq a) => FM k a -> FM k a -> Bool+submap :: (Ord k,Eq a) => FM k a -> FM k a -> Bool+sameMap :: (Ord k,Eq a) => FM k a -> FM k a -> Bool++toSeq :: (Ord k,S.Sequence seq) => FM k a -> seq (k,a)+keys :: (Ord k,S.Sequence seq) => FM k a -> seq k+mapWithKey :: Ord k => (k -> a -> b) -> FM k a -> FM k b+foldWithKey :: Ord k => (k -> a -> b -> b) -> b -> FM k a -> b+foldWithKey' :: Ord k => (k -> a -> b -> b) -> b -> FM k a -> b+filterWithKey :: Ord k => (k -> a -> Bool) -> FM k a -> FM k a+partitionWithKey :: Ord k => (k -> a -> Bool) -> FM k a -> (FM k a,FM k a)++minViewWithKey :: (Ord k,Monad m) => FM k a -> m ((k, a), FM k a)+minElemWithKey :: Ord k => FM k a -> (k,a)+maxViewWithKey :: (Ord k,Monad m) => FM k a -> m ((k, a), FM k a)+maxElemWithKey :: Ord k => FM k a -> (k,a)+foldrWithKey :: (k -> a -> b -> b) -> b -> FM k a -> b+foldlWithKey :: (b -> k -> a -> b) -> b -> FM k a -> b+foldrWithKey' :: (k -> a -> b -> b) -> b -> FM k a -> b+foldlWithKey' :: (b -> k -> a -> b) -> b -> FM k a -> b+toOrdSeq :: (Ord k,S.Sequence seq) => FM k a -> seq (k,a)++unionWithKey :: Ord k => (k -> a -> a -> a) -> FM k a -> FM k a -> FM k a+unionSeqWithKey :: (Ord k,S.Sequence seq) => (k -> a -> a -> a)+ -> seq (FM k a) -> FM k a+intersectionWithKey :: Ord k => (k -> a -> b -> c) -> FM k a -> FM k b -> FM k c++structuralInvariant :: Ord k => FM k a -> Bool+structuralInvariant = DM.valid+++empty = DM.empty+singleton = DM.singleton+fromSeq = fromSeqUsingInsertSeq+insert = DM.insert+insertSeq = insertSeqUsingFoldr+union = DM.union+unionSeq = DM.unions . S.toList+delete = DM.delete+deleteAll = DM.delete -- by finite map property+deleteSeq = deleteSeqUsingFoldr+null = DM.null+size = DM.size+member = DM.member+count = countUsingMember+lookup k m = case lookupM k m of+ Nothing -> error (moduleName ++ ".lookup: failed")+ Just x -> x+lookupM = DM.lookup+lookupAll = lookupAllUsingLookupM+lookupWithDefault = DM.findWithDefault+lookupAndDelete = lookupAndDeleteDefault+lookupAndDeleteM = lookupAndDeleteMDefault+lookupAndDeleteAll = lookupAndDeleteAllDefault+adjust = DM.adjust+adjustAll = DM.adjust+adjustOrInsert = adjustOrInsertUsingMember+adjustAllOrInsert = adjustOrInsertUsingMember+adjustOrDelete = DM.update+adjustOrDeleteAll = DM.update+strict xs = DM.fold (flip const) () xs `seq` xs+strictWith f xs = DM.fold (\x z -> f x `seq` z) () xs `seq` xs+map = fmap+fold = DM.fold+fold' f x xs = L.foldl' (flip f) x (DM.elems xs)+fold1 f xs = L.foldr1 f (DM.elems xs)+fold1' f xs = L.foldl1' (flip f) (DM.elems xs)+filter = DM.filter+partition = DM.partition+elements = elementsUsingFold++minView m = if DM.null m+ then fail (moduleName ++ ".minView: failed")+ else let ((k,x),m') = DM.deleteFindMin m + in return (x,m')+minElem = snd . DM.findMin+deleteMin = DM.deleteMin+unsafeInsertMin = DM.insert+maxView m = if DM.null m+ then fail (moduleName ++ ".maxView: failed")+ else let ((k,x),m') = DM.deleteFindMax m + in return (x,m')+maxElem = snd . DM.findMax+deleteMax = DM.deleteMax+unsafeInsertMax = DM.insert+foldr f x m = L.foldr f x (DM.elems m)+foldl f x m = L.foldl f x (DM.elems m)+foldr1 f m = L.foldr1 f (DM.elems m)+foldl1 f m = L.foldl1 f (DM.elems m)+foldr' f x m = L.foldr' f x (DM.elems m)+foldl' f x m = L.foldl' f x (DM.elems m)+foldr1' f m = L.foldr1' f (DM.elems m)+foldl1' f m = L.foldl1' f (DM.elems m)+unsafeFromOrdSeq = DM.fromAscList . S.toList+unsafeAppend = DM.union+filterLT k = fst . DM.split k+filterGT k = snd . DM.split k+filterLE k m = let (lt, mx, _ ) = DM.splitLookup k m in maybe lt (\x -> insert k x lt) mx+filterGE k m = let (_ , mx, gt) = DM.splitLookup k m in maybe gt (\x -> insert k x gt) mx+partitionLT_GE k m = let (lt, mx, gt) = DM.splitLookup k m in (lt, maybe gt (\x -> insert k x gt) mx)+partitionLE_GT k m = let (lt, mx, gt) = DM.splitLookup k m in (maybe lt (\x -> insert k x lt) mx, gt)+partitionLT_GT = DM.split+fromSeqWith f s = DM.fromListWith f (S.toList s)+fromSeqWithKey f s = DM.fromListWithKey f (S.toList s)+insertWith = DM.insertWith+insertWithKey = insertWithKeyUsingInsertWith+insertSeqWith = insertSeqWithUsingInsertWith+insertSeqWithKey = insertSeqWithKeyUsingInsertWithKey+unionl = DM.union+unionr = flip DM.union+unionWith = DM.unionWith+unionSeqWith = unionSeqWithUsingReduce+intersectionWith = DM.intersectionWith+difference = DM.difference+properSubset = DM.isProperSubmapOfBy (\_ _ -> True)+subset = DM.isSubmapOfBy (\_ _ -> True)+properSubmapBy = DM.isProperSubmapOfBy+submapBy = DM.isSubmapOfBy+sameMapBy = sameMapByUsingOrdLists+properSubmap = A.properSubmap+submap = A.submap+sameMap = A.sameMap++toSeq = toSeqUsingFoldWithKey+keys = keysUsingFoldWithKey+mapWithKey = DM.mapWithKey+foldWithKey = DM.foldWithKey+foldWithKey' f x m = L.foldl' (\b (k,a) -> f k a b) x (DM.toList m)+filterWithKey = DM.filterWithKey+partitionWithKey = DM.partitionWithKey++minViewWithKey m = if DM.null m+ then fail (moduleName ++ ".minViewWithKey: failed")+ else return (DM.deleteFindMin m)+minElemWithKey = DM.findMin+maxViewWithKey m = if DM.null m+ then fail (moduleName ++ ".maxViewWithKey: failed")+ else return (DM.deleteFindMax m)+maxElemWithKey = DM.findMax+foldrWithKey = DM.foldWithKey+foldrWithKey' f x m = L.foldr' (\(k,a) b -> f k a b) x (DM.toAscList m)+foldlWithKey f x m = L.foldl (\b (k,a) -> f b k a) x (DM.toAscList m)+foldlWithKey' f x m = L.foldl' (\b (k,a) -> f b k a) x (DM.toAscList m)+toOrdSeq = S.fromList . DM.toAscList++unionWithKey = DM.unionWithKey+unionSeqWithKey = unionSeqWithKeyUsingReduce+intersectionWithKey = DM.intersectionWithKey+++instance Ord k => A.AssocX (FM k) k where+ {empty = empty; singleton = singleton; fromSeq = fromSeq; insert = insert;+ insertSeq = insertSeq; union = union; unionSeq = unionSeq;+ delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq;+ null = null; size = size; member = member; count = count;+ lookup = lookup; lookupM = lookupM; lookupAll = lookupAll;+ lookupAndDelete = lookupAndDelete; lookupAndDeleteM = lookupAndDeleteM;+ lookupAndDeleteAll = lookupAndDeleteAll;+ lookupWithDefault = lookupWithDefault; adjust = adjust;+ adjustAll = adjustAll; adjustOrInsert = adjustOrInsert;+ adjustAllOrInsert = adjustAllOrInsert;+ adjustOrDelete = adjustOrDelete; adjustOrDeleteAll = adjustOrDeleteAll;+ fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; elements = elements;+ strict = strict; strictWith = strictWith;+ structuralInvariant = structuralInvariant; instanceName m = moduleName}++instance Ord k => A.OrdAssocX (FM k) k where+ {minView = minView; minElem = minElem; deleteMin = deleteMin;+ unsafeInsertMin = unsafeInsertMin; maxView = maxView; maxElem = maxElem;+ deleteMax = deleteMax; unsafeInsertMax = unsafeInsertMax;+ foldr = foldr; foldr' = foldr'; foldl = foldl; foldl' = foldl';+ foldr1 = foldr1; foldr1' = foldr1'; foldl1 = foldl1; foldl1' = foldl1';+ unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend;+ filterLT = filterLT; filterGT = filterGT; filterLE = filterLE;+ filterGE = filterGE; partitionLT_GE = partitionLT_GE;+ partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance Ord k => A.FiniteMapX (FM k) k where+ {fromSeqWith = fromSeqWith; fromSeqWithKey = fromSeqWithKey;+ insertWith = insertWith; insertWithKey = insertWithKey;+ insertSeqWith = insertSeqWith; insertSeqWithKey = insertSeqWithKey;+ unionl = unionl; unionr = unionr; unionWith = unionWith;+ unionSeqWith = unionSeqWith; intersectionWith = intersectionWith;+ difference = difference; properSubset = properSubset; subset = subset;+ properSubmapBy = properSubmapBy; submapBy = submapBy;+ sameMapBy = sameMapBy}++instance Ord k => A.OrdFiniteMapX (FM k) k++instance Ord k => A.Assoc (FM k) k where+ {toSeq = toSeq; keys = keys; mapWithKey = mapWithKey;+ foldWithKey = foldWithKey; foldWithKey' = foldWithKey';+ filterWithKey = filterWithKey;+ partitionWithKey = partitionWithKey}++instance Ord k => A.OrdAssoc (FM k) k where+ {minViewWithKey = minViewWithKey; minElemWithKey = minElemWithKey;+ maxViewWithKey = maxViewWithKey; maxElemWithKey = maxElemWithKey;+ foldrWithKey = foldrWithKey; foldrWithKey' = foldrWithKey';+ foldlWithKey = foldlWithKey; foldlWithKey' = foldlWithKey';+ toOrdSeq = toOrdSeq}++instance Ord k => A.FiniteMap (FM k) k where+ {unionWithKey = unionWithKey; unionSeqWithKey = unionSeqWithKey;+ intersectionWithKey = intersectionWithKey}++instance Ord k => A.OrdFiniteMap (FM k) k++instance (Ord k,Arbitrary k,Arbitrary a) => Arbitrary (FM k a) where+ arbitrary = do xs <- arbitrary+ return (Prelude.foldr (uncurry insert) empty xs)++ coarbitrary map = coarbitrary (A.toList map)
+ src/Data/Edison/Assoc/TernaryTrie.hs view
@@ -0,0 +1,1149 @@+-- |+-- Module : Data.Edison.Assoc.TernaryTrie+-- Copyright : Copyright (c) 2002 Andrew Bromage+-- License : MIT; see COPYRIGHT file for terms and conditions+--+-- Maintainer : robdockins AT fastmail DOT fm+-- Stability : stable+-- Portability : GHC, Hugs (MPTC and FD)+--+-- Finite maps implemented as ternary search tries++module Data.Edison.Assoc.TernaryTrie (+ -- * Type of ternary search tries+ FM,++ -- * AssocX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,lookup,lookupM,lookupAll,+ lookupAndDelete,lookupAndDeleteM,lookupAndDeleteAll,+ lookupWithDefault,adjust,adjustAll,adjustOrInsert,adjustAllOrInsert,+ adjustOrDelete,adjustOrDeleteAll,strict,strictWith,+ map,fold,fold',fold1,fold1',filter,partition,elements,structuralInvariant,++ -- * Assoc operations+ toSeq,keys,mapWithKey,foldWithKey,foldWithKey',filterWithKey,partitionWithKey,++ -- * FiniteMapX operations+ fromSeqWith,fromSeqWithKey,insertWith,insertWithKey,insertSeqWith,+ insertSeqWithKey,unionl,unionr,unionWith,unionSeqWith,intersectionWith,+ difference,properSubset,subset,properSubmapBy,submapBy,sameMapBy,+ properSubmap,submap,sameMap,++ -- * FiniteMap operations+ unionWithKey,unionSeqWithKey,intersectionWithKey,++ -- * OrdAssocX operations+ minView, minElem, deleteMin, unsafeInsertMin,+ maxView, maxElem, deleteMax, unsafeInsertMax,+ foldr, foldr', foldr1, foldr1', foldl, foldl', foldl1, foldl1',+ unsafeFromOrdSeq, unsafeAppend, filterLT, filterLE, filterGT, filterGE,+ partitionLT_GE, partitionLE_GT, partitionLT_GT,++ -- * OrdAssoc operations+ minViewWithKey, minElemWithKey, maxViewWithKey, maxElemWithKey,+ foldrWithKey, foldrWithKey', foldlWithKey, foldlWithKey',+ toOrdSeq,++ -- * Other supported operations+ mergeVFM, mergeKVFM,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,map,lookup,foldr,foldl,foldr1,foldl1,filter)+import qualified Prelude+import Data.Edison.Prelude+import qualified Data.Edison.Assoc as A+import qualified Data.Edison.Seq as S+import qualified Data.List as L+import Control.Monad.Identity+import Data.Monoid+import Data.Edison.Assoc.Defaults+import Test.QuickCheck (Arbitrary(..), variant)++import Maybe (isNothing)++-- signatures for exported functions+moduleName :: String+empty :: Ord k => FM k a+singleton :: Ord k => [k] -> a -> FM k a+fromSeq :: (Ord k,S.Sequence seq) => seq ([k],a) -> FM k a+insert :: Ord k => [k] -> a -> FM k a -> FM k a+insertSeq :: (Ord k,S.Sequence seq) => seq ([k],a) -> FM k a -> FM k a+union :: Ord k => FM k a -> FM k a -> FM k a+unionSeq :: (Ord k,S.Sequence seq) => seq (FM k a) -> FM k a+delete :: Ord k => [k] -> FM k a -> FM k a+deleteAll :: Ord k => [k] -> FM k a -> FM k a+deleteSeq :: (Ord k,S.Sequence seq) => seq [k] -> FM k a -> FM k a+null :: Ord k => FM k a -> Bool+size :: Ord k => FM k a -> Int+member :: Ord k => [k] -> FM k a -> Bool+count :: Ord k => [k] -> FM k a -> Int+lookup :: Ord k => [k] -> FM k a -> a+lookupM :: (Ord k, Monad rm) => [k] -> FM k a -> rm a+lookupAll :: (Ord k,S.Sequence seq) => [k] -> FM k a -> seq a+lookupAndDelete :: Ord k => [k] -> FM k a -> (a, FM k a)+lookupAndDeleteM :: (Ord k, Monad rm) => [k] -> FM k a -> rm (a, FM k a)+lookupAndDeleteAll :: (Ord k, S.Sequence seq) => [k] -> FM k a -> (seq a,FM k a)+lookupWithDefault :: Ord k => a -> [k] -> FM k a -> a+adjust :: Ord k => (a -> a) -> [k] -> FM k a -> FM k a+adjustAll :: Ord k => (a -> a) -> [k] -> FM k a -> FM k a+adjustOrInsert :: Ord k => (a -> a) -> a -> [k] -> FM k a -> FM k a+adjustAllOrInsert :: Ord k => (a -> a) -> a -> [k] -> FM k a -> FM k a+adjustOrDelete :: Ord k => (a -> Maybe a) -> [k] -> FM k a -> FM k a+adjustOrDeleteAll :: Ord k => (a -> Maybe a) -> [k] -> FM k a -> FM k a+strict :: FM k a -> FM k a+strictWith :: (a -> b) -> FM k a -> FM k a+map :: Ord k => (a -> b) -> FM k a -> FM k b+fold :: Ord k => (a -> b -> b) -> b -> FM k a -> b+fold1 :: Ord k => (a -> a -> a) -> FM k a -> a+fold' :: Ord k => (a -> b -> b) -> b -> FM k a -> b+fold1' :: Ord k => (a -> a -> a) -> FM k a -> a+filter :: Ord k => (a -> Bool) -> FM k a -> FM k a+partition :: Ord k => (a -> Bool) -> FM k a -> (FM k a, FM k a)+elements :: (Ord k,S.Sequence seq) => FM k a -> seq a++fromSeqWith :: (Ord k,S.Sequence seq) => + (a -> a -> a) -> seq ([k],a) -> FM k a+fromSeqWithKey :: (Ord k,S.Sequence seq) => ([k] -> a -> a -> a) -> seq ([k],a) -> FM k a+insertWith :: Ord k => (a -> a -> a) -> [k] -> a -> FM k a -> FM k a+insertWithKey :: Ord k => ([k] -> a -> a -> a) -> [k] -> a -> FM k a -> FM k a+insertSeqWith :: (Ord k,S.Sequence seq) => + (a -> a -> a) -> seq ([k],a) -> FM k a -> FM k a+insertSeqWithKey :: (Ord k,S.Sequence seq) => + ([k] -> a -> a -> a) -> seq ([k],a) -> FM k a -> FM k a+unionl :: Ord k => FM k a -> FM k a -> FM k a+unionr :: Ord k => FM k a -> FM k a -> FM k a+unionWith :: Ord k => (a -> a -> a) -> FM k a -> FM k a -> FM k a+unionSeqWith :: (Ord k,S.Sequence seq) => + (a -> a -> a) -> seq (FM k a) -> FM k a+intersectionWith :: Ord k => (a -> b -> c) -> FM k a -> FM k b -> FM k c+difference :: Ord k => FM k a -> FM k b -> FM k a+properSubset :: Ord k => FM k a -> FM k b -> Bool +subset :: Ord k => FM k a -> FM k b -> Bool +properSubmapBy :: Ord k => (a -> a -> Bool) -> FM k a -> FM k a -> Bool+submapBy :: Ord k => (a -> a -> Bool) -> FM k a -> FM k a -> Bool+sameMapBy :: Ord k => (a -> a -> Bool) -> FM k a -> FM k a -> Bool+properSubmap :: (Ord k, Eq a) => FM k a -> FM k a -> Bool+submap :: (Ord k, Eq a) => FM k a -> FM k a -> Bool+sameMap :: (Ord k, Eq a) => FM k a -> FM k a -> Bool++toSeq :: (Ord k,S.Sequence seq) => FM k a -> seq ([k],a)+keys :: (Ord k,S.Sequence seq) => FM k a -> seq [k]+mapWithKey :: Ord k => ([k] -> a -> b) -> FM k a -> FM k b+foldWithKey :: Ord k => ([k] -> a -> b -> b) -> b -> FM k a -> b+foldWithKey' :: Ord k => ([k] -> a -> b -> b) -> b -> FM k a -> b+filterWithKey :: Ord k => ([k] -> a -> Bool) -> FM k a -> FM k a+partitionWithKey :: Ord k => ([k] -> a -> Bool) -> FM k a -> (FM k a, FM k a)+unionWithKey :: Ord k => ([k] -> a -> a -> a) -> FM k a -> FM k a -> FM k a+unionSeqWithKey :: (Ord k,S.Sequence seq) => + ([k] -> a -> a -> a) -> seq (FM k a) -> FM k a+intersectionWithKey :: Ord k => ([k] -> a -> b -> c) -> FM k a -> FM k b -> FM k c++foldr :: Ord k => (a -> b -> b) -> b -> FM k a -> b+foldr1 :: Ord k => (a -> a -> a) -> FM k a -> a+foldr' :: Ord k => (a -> b -> b) -> b -> FM k a -> b+foldr1' :: Ord k => (a -> a -> a) -> FM k a -> a++foldrWithKey :: Ord k => ([k] -> a -> b -> b) -> b -> FM k a -> b+foldrWithKey' :: Ord k => ([k] -> a -> b -> b) -> b -> FM k a -> b+foldlWithKey :: Ord k => (b -> [k] -> a -> b) -> b -> FM k a -> b+foldlWithKey' :: Ord k => (b -> [k] -> a -> b) -> b -> FM k a -> b+toOrdSeq :: (Ord k,S.Sequence seq) => FM k a -> seq ([k],a)++moduleName = "Data.Edison.Assoc.TernaryTrie"+++data FM k a+ = FM !(Maybe a) !(FMB k a)++data FMB k v+ = E+ | I !Int !k !(Maybe v) !(FMB k v) !(FMB' k v) !(FMB k v)++newtype FMB' k v+ = FMB' (FMB k v)++balance :: Int+balance = 6++sizeFMB :: FMB k v -> Int+sizeFMB E = 0+sizeFMB (I size _ _ _ _ _) = size++mkFMB :: k -> Maybe v -> FMB k v -> FMB' k v -> FMB k v -> FMB k v+mkFMB k v l m r+ = I (1 + sizeFMB l + sizeFMB r) k v l m r++lookupFMB :: (Ord k) => [k] -> FMB k v -> Maybe v+lookupFMB [] _+ = Nothing+lookupFMB nk@(x:xs) E+ = Nothing+lookupFMB nk@(x:xs) (I _ k v l m@(FMB' fmbm) r)+ = case compare x k of+ LT -> lookupFMB nk l+ GT -> lookupFMB nk r+ EQ -> if L.null xs then v else lookupFMB xs fmbm++listToFMB :: [k] -> (Maybe v -> Maybe v) -> FMB k v+listToFMB [x] fv = mkFMB x (fv Nothing) E (FMB' E) E+listToFMB (x:xs) fv = mkFMB x Nothing E (FMB' $ listToFMB xs fv) E+listToFMB _ _ = error "TernaryTrie.listToFMB: bug!"++addToFMB :: (Ord k) => [k] -> (Maybe v -> Maybe v) -> FMB k v -> FMB k v+addToFMB xs combiner E+ = listToFMB xs combiner+addToFMB nk@(x:xs) combiner (I size k v l m@(FMB' fmbm) r)+ = case compare x k of+ LT -> mkBalancedFMB k v (addToFMB nk combiner l) m r+ GT -> mkBalancedFMB k v l m (addToFMB nk combiner r)+ EQ -> case xs of+ [] -> I size k (combiner v) l m r+ _ -> I size k v l (FMB' $ addToFMB xs combiner fmbm) r+addToFMB _ _ _ = error "TernaryTrie.addToFMB: bug!"++addToFM :: (Ord k) => [k] -> (Maybe v -> Maybe v) -> FM k v -> FM k v+addToFM [] combiner (FM n fmb)+ = FM (combiner n) fmb+addToFM xs combiner (FM n fmb)+ = FM n (addToFMB xs combiner fmb)++lookupAndDelFromFMB :: (Ord k) => z -> (v -> FMB k v -> z) -> [k] -> FMB k v -> z+lookupAndDelFromFMB onFail cont xs E = onFail+lookupAndDelFromFMB onFail cont nk@(x:xs) (I size k v l m@(FMB' fmbm) r)+ = case compare x k of+ LT -> lookupAndDelFromFMB onFail (\w l' -> cont w (mkBalancedFMB k v l' m r)) nk l+ GT -> lookupAndDelFromFMB onFail (\w r' -> cont w (mkBalancedFMB k v l m r')) nk r+ EQ -> case xs of+ [] -> case v of+ Nothing -> onFail+ Just w -> case fmbm of+ E -> cont w (appendFMB l r)+ _ -> cont w (I size k Nothing l m r)+ _ -> lookupAndDelFromFMB onFail (\w m' -> cont w (I size k v l (FMB' m') r)) xs fmbm+lookupAndDelFromFMB _ _ _ _ = error "TernaryTrie.lookupAndDelFromFMB: bug!"++lookupAndDelFromFM :: (Ord k) => z -> (v -> FM k v -> z) -> [k] -> FM k v -> z+lookupAndDelFromFM onFail cont [] (FM Nothing fmb) = onFail+lookupAndDelFromFM onFail cont [] (FM (Just v) fmb) = cont v (FM Nothing fmb)+lookupAndDelFromFM onFail cont xs (FM n fmb) =+ lookupAndDelFromFMB onFail (\w fmb' -> cont w (FM n fmb')) xs fmb+++delFromFMB :: (Ord k) => [k] -> FMB k v -> FMB k v+delFromFMB xs E+ = E+delFromFMB nk@(x:xs) (I size k v l m@(FMB' fmbm) r)+ = case compare x k of+ LT -> mkBalancedFMB k v (delFromFMB nk l) m r+ GT -> mkBalancedFMB k v l m (delFromFMB nk r)+ EQ -> case xs of+ [] -> case fmbm of+ E -> appendFMB l r+ _ -> I size k Nothing l m r+ _ -> I size k v l (FMB' $ delFromFMB xs fmbm) r+delFromFMB _ _ = error "TernaryTrie.delFromFMB: bug!"+++delFromFM :: (Ord k) => [k] -> FM k v -> FM k v+delFromFM [] (FM n fmb)+ = FM Nothing fmb+delFromFM xs (FM n fmb)+ = FM n (delFromFMB xs fmb)+++mkBalancedFMB :: k -> Maybe v -> FMB k v -> FMB' k v -> FMB k v -> FMB k v+mkBalancedFMB k v l m r+ | size_l + size_r < 2+ = mkFMB k v l m r+ | size_r > balance * size_l -- Right tree too big+ = case r of+ I _ _ _ rl _ rr+ | sizeFMB rl < 2 * sizeFMB rr+ -> single_L l m r+ | otherwise+ -> double_L l m r+ _ -> error "TernaryTrie.mkBalancedFMB: bug!"++ | size_l > balance * size_r -- Left tree too big+ = case l of+ I _ _ _ ll _ lr+ | sizeFMB lr < 2 * sizeFMB ll+ -> single_R l m r+ | otherwise+ -> double_R l m r+ _ -> error "TernaryTrie.mkBalancedFMB: bug!"++ | otherwise -- No imbalance+ = mkFMB k v l m r+ where+ size_l = sizeFMB l+ size_r = sizeFMB r++ single_L l m (I _ k_r v_r rl rm rr)+ = mkFMB k_r v_r (mkFMB k v l m rl) rm rr+ single_L _ _ _ = error "TernaryTrie:mkBalancedFMB: bug!"++ double_L l m (I _ k_r v_r (I _ k_rl v_rl rll rlm rlr) rm rr)+ = mkFMB k_rl v_rl (mkFMB k v l m rll) rlm (mkFMB k_r v_r rlr rm rr)+ double_L _ _ _ = error "TernaryTrie:mkBalancedFMB: bug!"++ single_R (I _ k_l v_l ll lm lr) m r+ = mkFMB k_l v_l ll lm (mkFMB k v lr m r)+ single_R _ _ _ = error "TernaryTrie:mkBalancedFMB: bug!"++ double_R (I _ k_l v_l ll lm (I _ k_lr v_lr lrl lrm lrr)) m r+ = mkFMB k_lr v_lr (mkFMB k_l v_l ll lm lrl) lrm (mkFMB k v lrr m r)+ double_R _ _ _ = error "TernaryTrie:mkBalancedFMB: bug!"+++mkVBalancedFMB :: k -> Maybe v -> FMB k v -> FMB' k v -> FMB k v -> FMB k v+mkVBalancedFMB k v E m E+ = mkFMB k v E m E+mkVBalancedFMB k v l@E m r@(I _ kr vr rl rm rr)+ = mkBalancedFMB kr vr (mkVBalancedFMB k v l m rl) rm rr+mkVBalancedFMB k v l@(I _ kl vl ll lm lr) m r@E+ = mkBalancedFMB kl vl ll lm (mkVBalancedFMB k v lr m r)+mkVBalancedFMB k v l@(I _ kl vl ll lm lr) m r@(I _ kr vr rl rm rr)+ | balance * size_l < size_r+ = mkBalancedFMB kr vr (mkVBalancedFMB k v l m rl) rm rr+ | balance * size_r < size_l+ = mkBalancedFMB kl vl ll lm (mkVBalancedFMB k v lr m r)+ | otherwise+ = mkFMB k v l m r+ where+ size_l = sizeFMB l+ size_r = sizeFMB r++ -- Constraint: All keys in the first FMB are less than+ -- that in the second FMB.+appendFMB :: FMB k v -> FMB k v -> FMB k v+appendFMB E m2 = m2+appendFMB m1 E = m1+appendFMB fmb1@(I size1 k1 v1 l1 m1 r1) fmb2@(I size2 k2 v2 l2 m2 r2)+ | size1 > size2+ = mkVBalancedFMB k1 v1 l1 m1 (appendFMB r1 fmb2)+ | otherwise+ = mkVBalancedFMB k2 v2 (appendFMB fmb1 l2) m2 r2++mapVFM :: (Maybe a -> Maybe b) -> FM k a -> FM k b+mapVFM f (FM n fmb)+ = FM (f n) (mapVFMB f fmb)++mapVFMB :: (Maybe a -> Maybe b) -> FMB k a -> FMB k b+mapVFMB f m+ = mapVFMB' m+ where+ mapVFMB' E = E+ mapVFMB' (I _ k v l (FMB' m) r)+ = case (mapVFMB' m, f v) of+ (E,Nothing) -> appendFMB (mapVFMB' l) (mapVFMB' r)+ (m',v') -> mkVBalancedFMB k v'+ (mapVFMB' l) (FMB' m') (mapVFMB' r)++mapKVFM :: ([k] -> Maybe a -> Maybe b) -> FM k a -> FM k b+mapKVFM f (FM n fmb)+ = FM (f [] n) (mapKVFMB [] fmb)+ where+ mapKVFMB _ E = E+ mapKVFMB ks (I size k v l (FMB' m) r)+ = mkVBalancedFMB k (f (reverse (k:ks)) v)+ (mapKVFMB ks l)+ (FMB' (mapKVFMB (k:ks) m))+ (mapKVFMB ks r)++nullFMB :: FMB k v -> Bool+nullFMB E = True+nullFMB (I _ _ v l (FMB' m) r)+ = case v of+ Just _ -> False+ Nothing -> nullFMB l && nullFMB m && nullFMB r++nullFM :: FM k v -> Bool+nullFM (FM (Just _) _) = False+nullFM (FM Nothing fmb) = nullFMB fmb++data FMBCtx k v+ = T+ | L !k !(Maybe v) !(FMBCtx k v) !(FMB' k v) !(FMB k v)+ | R !k !(Maybe v) !(FMB k v) !(FMB' k v) !(FMBCtx k v)++splayFMB :: (Ord k) => k -> FMB k a -> (Maybe a, FMB k a, FMB' k a, FMB k a)+splayFMB key fmb+ = splaydown T fmb+ where+ splaydown ctx E+ = splayup ctx Nothing E (FMB' E) E+ splaydown ctx y@(I _ k v l m r)+ = case compare key k of+ LT -> splaydown (L k v ctx m r) l+ GT -> splaydown (R k v l m ctx) r+ EQ -> splayup ctx v l m r++ splayup ctx v l m r+ = splayup' ctx l r+ where+ splayup' T l r+ = (v, l, m, r)+ splayup' (L ck cv ctx cm cr) tl tr+ = splayup' ctx tl (mkVBalancedFMB ck cv tr cm cr)+ splayup' (R ck cv cl cm ctx) tl tr+ = splayup' ctx (mkVBalancedFMB ck cv cl cm tl) tr++mergeVFMB :: (Ord k) => (Maybe a -> Maybe b -> Maybe c) ->+ FMB k a -> FMB k b -> FMB k c+mergeVFMB f fmbx fmby+ = mergeVFMB' fmbx fmby+ where+ mergeVFMB' E E+ = E+ mergeVFMB' E fmby@(I _ k v l (FMB' m) r)+ = mapVFMB (\v -> f Nothing v) fmby+ mergeVFMB' fmbx@(I _ k v l (FMB' m) r) E+ = mapVFMB (\v -> f v Nothing) fmbx+ mergeVFMB' fmbx@(I sizex kx vx lx (FMB' mx) rx)+ fmby@(I sizey ky vy ly (FMB' my) ry)+ | sizex >= sizey+ = let (vy, ly, FMB' my, ry) = splayFMB kx fmby+ in case (mergeVFMB' mx my, f vx vy) of+ (E,Nothing) -> appendFMB (mergeVFMB' lx ly) (mergeVFMB' rx ry)+ (m',v) -> mkVBalancedFMB kx v+ (mergeVFMB' lx ly)+ (FMB' m')+ (mergeVFMB' rx ry)+ | otherwise+ = let (vx, lx, FMB' mx, rx) = splayFMB ky fmbx+ in case (mergeVFMB' mx my, f vx vy) of+ (E,Nothing) -> appendFMB (mergeVFMB' lx ly) (mergeVFMB' rx ry)+ (m',v) -> mkVBalancedFMB ky v+ (mergeVFMB' lx ly)+ (FMB' m')+ (mergeVFMB' rx ry)++mergeVFM :: (Ord k) => (Maybe a -> Maybe b -> Maybe c) ->+ FM k a -> FM k b -> FM k c+mergeVFM f (FM vx fmbx) (FM vy fmby)+ = FM (f vx vy) (mergeVFMB f fmbx fmby)+++mergeKVFMB :: (Ord k) => ([k] -> Maybe a -> Maybe b -> Maybe c) ->+ FMB k a -> FMB k b -> FMB k c+mergeKVFMB f fmbx fmby+ = mergeKVFMB' [] fmbx fmby+ where+ mergeKVFMB' ks E E+ = E+ mergeKVFMB' ks E fmby+ = mergeKVFMBs (\k v -> f k Nothing v) ks fmby+ mergeKVFMB' ks fmbx E+ = mergeKVFMBs (\k v -> f k v Nothing) ks fmbx+ mergeKVFMB' ks fmbx@(I sizex kx vx lx (FMB' mx) rx)+ fmby@(I sizey ky vy ly (FMB' my) ry)+ | sizex >= sizey+ = let (vy, ly, FMB' my, ry) = splayFMB kx fmby+ ks' = reverse (kx:ks)+ in case (mergeKVFMB' ks' mx my, f ks' vx vy) of+ (E,Nothing) -> appendFMB+ (mergeKVFMB' ks lx ly)+ (mergeKVFMB' ks rx ry)+ (m',v) -> mkVBalancedFMB kx v+ (mergeKVFMB' ks lx ly)+ (FMB' m')+ (mergeKVFMB' ks rx ry)+ | otherwise+ = let (vx, lx, FMB' mx, rx) = splayFMB ky fmbx+ ks' = reverse (ky:ks)+ in case (mergeKVFMB' ks' mx my, f ks' vx vy) of+ (E,Nothing) -> appendFMB+ (mergeKVFMB' ks lx ly)+ (mergeKVFMB' ks rx ry)+ (m',v) -> mkVBalancedFMB ky v+ (mergeKVFMB' ks lx ly)+ (FMB' m')+ (mergeKVFMB' ks rx ry)++ mergeKVFMBs f ks fmb+ = mergeKVFMBs' ks fmb+ where+ mergeKVFMBs' ks E+ = E+ mergeKVFMBs' ks (I s k v l (FMB' m) r)+ = case (mergeKVFMBs' (k:ks) m, f (reverse (k:ks)) v) of+ (E, Nothing) -> appendFMB+ (mergeKVFMBs' ks l)+ (mergeKVFMBs' ks r)+ (m,v) -> mkVBalancedFMB k v+ (mergeKVFMBs' ks l)+ (FMB' m)+ (mergeKVFMBs' ks r)++mergeKVFM :: (Ord k) => ([k] -> Maybe a -> Maybe b -> Maybe c) ->+ FM k a -> FM k b -> FM k c+mergeKVFM f (FM vx fmbx) (FM vy fmby)+ = FM (f [] vx vy) (mergeKVFMB f fmbx fmby)+++-- The public interface.+-- ++-- AssocX++empty = FM Nothing E++singleton [] v = FM (Just v) E+singleton xs v = FM Nothing (listToFMB xs (\_ -> Just v))++fromSeq = fromSeqUsingInsertSeq++insert k v fm = addToFM k (\_ -> Just v) fm++insertSeq = insertSeqUsingFoldr++union = mergeVFM mplus++unionSeq = unionSeqUsingReduce++delete k fm = delFromFM k fm++deleteAll = delete++deleteSeq = deleteSeqUsingFoldr++null = nullFM++size (FM k fmb) + | isNothing k = fmb_size fmb 0+ | otherwise = fmb_size fmb 1+ where fmb_size E k = k+ fmb_size (I _ _ Nothing l (FMB' m) r) k = fmb_size l $ fmb_size m $ fmb_size r k+ fmb_size (I _ _ _ l (FMB' m) r ) k = fmb_size l $ fmb_size m $ fmb_size r $! k+1+++member = memberUsingLookupM++count = countUsingMember++lookup m k = runIdentity (lookupM m k)++lookupM [] (FM Nothing _)+ = fail "TernaryTrie.lookup: lookup failed"+lookupM [] (FM (Just v) _)+ = return v+lookupM xs (FM _ fmb)+ = case lookupFMB xs fmb of+ Nothing -> fail "TernaryTrie.lookup: lookup failed"+ Just v -> return v++lookupAll = lookupAllUsingLookupM++lookupAndDelete =+ lookupAndDelFromFM + (error "TernaryTrie.lookupAndDelete: lookup failed")+ (,)++lookupAndDeleteM = + lookupAndDelFromFM+ (fail "TernaryTrie.lookupAndDeleteM: lookup failed")+ (\w m -> return (w,m))++lookupAndDeleteAll k m =+ lookupAndDelFromFM+ (S.empty,m)+ (\w m' -> (S.singleton w,m'))+ k m++lookupWithDefault = lookupWithDefaultUsingLookupM++adjust f k+ = addToFM k (\mv -> case mv of+ Nothing -> mv+ Just v -> Just (f v))++adjustAll = adjust++adjustOrInsert f z k + = addToFM k (\mv -> case mv of+ Nothing -> Just z+ Just v -> Just (f v))++adjustAllOrInsert = adjustOrInsert++adjustOrDelete f k+ = addToFM k (\mv -> case mv of+ Nothing -> mv+ Just v -> f v)++adjustOrDeleteAll = adjustOrDelete++map f+ = mapVFM (\mv -> case mv of+ Nothing -> Nothing+ Just v -> Just (f v))++fold = foldr+fold' = foldr'++foldr op z (FM n fmb)+ = foldMV n . foldFMB fmb $ z+ where+ foldMV Nothing = id+ foldMV (Just v) = op v++ foldFMB E+ = id+ foldFMB (I _ _ v l (FMB' m) r)+ = foldFMB l . foldMV v . foldFMB m . foldFMB r++foldrWithKey f z (FM n fmb)+ = foldMV [] n . foldFMB id fmb $ z+ where+ foldMV ks Nothing = id+ foldMV ks (Just v) = f ks v++ foldFMB kf E = id+ foldFMB kf (I _ k mv l (FMB' m) r)+ = foldFMB kf l . foldMV (kf [k]) mv . foldFMB (kf . (k:)) m . foldFMB kf r++foldlWithKey f z (FM n fmb)+ = foldFMB id fmb . foldMV [] n $ z+ where+ g k x a = f a k x++ foldMV ks Nothing = id+ foldMV ks (Just v) = g ks v++ foldFMB kf E = id+ foldFMB kf (I _ k mv l (FMB' m) r)+ = foldFMB kf r . foldFMB (kf . (k:)) m . foldMV (kf [k]) mv . foldFMB kf l++foldrWithKey' = foldrWithKey+foldlWithKey' = foldlWithKey++foldl op z (FM n fmb)+ = foldFMB fmb . foldMV n $ z+ where + foldMV Nothing = id+ foldMV (Just v) = (flip op) v++ foldFMB E = id+ foldFMB (I _ _ v l (FMB' m) r)+ = foldFMB r . foldFMB m . foldMV v . foldFMB l+++-- FIXME, undestand this code to strictify it+foldr' = foldr+foldl' = foldl++foldr1 f fm = + case maxView fm of+ Just (z,fm') -> foldr f z fm'+ Nothing -> error $ moduleName++".foldr1: empty map"++foldl1 f fm =+ case minView fm of+ Just (z,fm') -> foldl f z fm'+ Nothing -> error $ moduleName++".foldl1: empty map"+++basecase Nothing = \j n -> n+basecase (Just x) = \j n -> j x++comb f p1 p2+ = \j n -> p1 (\x -> p2 (\y -> j (f x y)) (j x)) (p2 j n)++fold1 f (FM mv fmb)+ = comb f (basecase mv) (fold1FMB fmb) id (error $ moduleName++".fold1: empty map")+ where+ fold1FMB E+ = \j n -> n+ fold1FMB (I _ _ mv l (FMB' m) r)+ = comb f (basecase mv) $ comb f (fold1FMB l) $ comb f (fold1FMB m) $ (fold1FMB r)++fold1' = fold1++{-+FIXME -- can these be somehow fixed to have the right order...++foldr1 f (FM v fmb)+ = comb f (basecase v) (fold1FMB fmb) id (error $ moduleName++".foldr1: empty map")+ where+ fold1FMB E+ = \j n -> n+ fold1FMB (I _ _ v l (FMB' m) r)+ = comb f (fold1FMB l) $ comb f (basecase v) $ comb f (fold1FMB m) $ (fold1FMB r)+++foldl1 f (FM v fmb)+ = comb f (fold1FMB fmb) (basecase v) id (error $ moduleName++".foldl1: empty map")+ where+ fold1FMB E+ = \j n -> n+ fold1FMB (I _ _ v l (FMB' m) r)+ = comb f (fold1FMB r) $ comb f (fold1FMB m) $ comb f (basecase v) $ (fold1FMB l)+-}++++-- FIXME, undestand this code to strictify it+foldr1' = foldr1+foldl1' = foldl1+++filter p = mapVFM (\mv -> case mv of+ Nothing -> mv+ Just v -> if p v then mv else Nothing)++partition = partitionUsingFilter++elements = elementsUsingFold++strict z@(FM v fmb) = strictFMB fmb `seq` z+ where strictFMB n@E = n+ strictFMB n@(I i k v l (FMB' m) r) =+ strictFMB l `seq` strictFMB m `seq` strictFMB r `seq` n++strictWith f z@(FM v fmb) = f' v `seq` strictWithFMB fmb `seq` z+ where f' v@Nothing = v+ f' v@(Just x) = f x `seq` v++ strictWithFMB n@E = n+ strictWithFMB n@(I i k v l (FMB' m) r) =+ f' v `seq` strictWithFMB l `seq` strictWithFMB m `seq` strictWithFMB r `seq` n+++-- FiniteMapX++fromSeqWith = fromSeqWithUsingInsertSeqWith++fromSeqWithKey = fromSeqWithKeyUsingInsertSeqWithKey++insertWith f k v+ = addToFM k (\vem ->+ case vem of+ Nothing -> Just v+ Just ve -> Just (f ve v))++insertWithKey = insertWithKeyUsingInsertWith++insertSeqWith = insertSeqWithUsingInsertWith++insertSeqWithKey = insertSeqWithKeyUsingInsertWithKey++unionl = union+unionr = flip union++unionWith f = unionWithKey (const f)++unionSeqWith = unionSeqWithUsingReduce++intersectionWith f = intersectionWithKey (const f)++difference mx my+ = mergeVFM (\v1 v2 -> case v2 of+ Nothing -> v1+ Just _ -> Nothing) mx my++properSubset = properSubsetUsingSubset++subset (FM nx fmbx) (FM ny fmby)+ = subsetEqM nx ny && subsetEqFMB fmbx fmby+ where+ subsetEqM Nothing _ = True+ subsetEqM (Just _) Nothing = False+ subsetEqM (Just _) (Just _) = True++ subsetEqFMB E _ = True+ subsetEqFMB fmbx@(I _ _ _ _ _ _) E+ = nullFMB fmbx+ subsetEqFMB fmbx@(I sizex kx vx lx (FMB' mx) rx)+ fmby@(I sizey ky vy ly (FMB' my) ry)+ | sizex >= sizey+ = let (vy, ly, FMB' my, ry) = splayFMB kx fmby+ in subsetEqM vx vy+ && subsetEqFMB lx ly+ && subsetEqFMB mx my+ && subsetEqFMB rx ry+ | otherwise+ = let (vx, lx, FMB' mx, rx) = splayFMB ky fmbx+ in subsetEqM vx vy+ && subsetEqFMB lx ly+ && subsetEqFMB mx my+ && subsetEqFMB rx ry+++submapBy = submapByUsingLookupM+properSubmapBy = properSubmapByUsingSubmapBy+sameMapBy = sameMapByUsingSubmapBy+properSubmap = A.properSubmap+submap = A.submap+sameMap = A.sameMap++-- Assoc++toSeq = toSeqUsingFoldWithKey++keys = keysUsingFoldWithKey++mapWithKey f+ = mapKVFM (\k mv -> case mv of+ Nothing -> Nothing+ Just v -> Just (f k v))++foldWithKey op r (FM n fmb)+ = foldWithKeyB [] n . foldWithKeyFM [] fmb $ r+ where+ foldWithKeyB k Nothing = id+ foldWithKeyB k (Just v) = op k v++ foldWithKeyFM ks E = id+ foldWithKeyFM ks (I _ k v l (FMB' m) r)+ = foldWithKeyFM ks l+ . foldWithKeyB (reverse (k:ks)) v+ . foldWithKeyFM (k:ks) m+ . foldWithKeyFM ks r+++-- FIXME, make this strict+foldWithKey' = foldWithKey+++filterWithKey f+ = mapKVFM (\k mv -> case mv of+ Nothing -> mv+ Just v -> if f k v then mv else Nothing)++partitionWithKey f m+ = (filterWithKey f m, filterWithKey (\k v -> not (f k v)) m)++-- FiniteMap++unionWithKey f+ = mergeKVFM (\k v1m v2m ->+ case v1m of+ Nothing -> v2m+ Just v1 ->+ case v2m of+ Nothing -> v1m+ Just v2 -> Just (f k v1 v2))++unionSeqWithKey = unionSeqWithKeyUsingReduce++intersectionWithKey f+ = mergeKVFM (\k v1m v2m ->+ case v1m of+ Nothing -> Nothing+ Just v1 ->+ case v2m of+ Nothing -> Nothing+ Just v2 -> Just (f k v1 v2))++-- OrdAssocX++minViewFMB :: Monad m => FMB k a -> (FMB k a -> FM k a) -> m (a, FM k a)+minViewFMB E f = fail $ moduleName++".minView: empty map"+minViewFMB (I i k (Just v) E m r) f = return (v, f (I i k Nothing E m r))+minViewFMB (I i k Nothing E (FMB' E) r) f = error $ moduleName++".minView: bug!"+minViewFMB (I i k Nothing E (FMB' m) r) f = minViewFMB m (\m' -> f (mkVBalancedFMB k Nothing E (FMB' m') r))+minViewFMB (I i k mv l m r) f = minViewFMB l (\l' -> f (mkVBalancedFMB k mv l' m r))++minView :: Monad m => FM k a -> m (a,FM k a)+minView (FM (Just v) fmb) = return (v, FM Nothing fmb)+minView (FM Nothing fmb) = minViewFMB fmb (FM Nothing)++minViewWithKeyFMB :: Monad m => FMB k a -> ([k] -> [k]) -> (FMB k a -> FM k a) -> m (([k],a),FM k a)+minViewWithKeyFMB E fk f = fail $ moduleName++".minView: empty map"+minViewWithKeyFMB (I i k (Just v) E m r) kf f = return ((kf [k],v),f (I i k Nothing E m r))+minViewWithKeyFMB (I i k Nothing E (FMB' E) r) kf f = error $ moduleName++".minViewWithKey: bug!"+minViewWithKeyFMB (I i k Nothing E (FMB' m) r) kf f = minViewWithKeyFMB m (kf . (k:)) + (\m' -> f (mkVBalancedFMB k Nothing E (FMB' m') r))+minViewWithKeyFMB (I i k mv l m r) kf f = minViewWithKeyFMB l kf+ (\l' -> f (mkVBalancedFMB k mv l' m r))++minViewWithKey :: Monad m => FM k a -> m (([k],a),FM k a)+minViewWithKey (FM (Just v) fmb) = return (([],v),FM Nothing fmb)+minViewWithKey (FM Nothing fmb) = minViewWithKeyFMB fmb id (FM Nothing)+++minElemFMB :: FMB k a -> a+minElemFMB E = error $ moduleName++".minElem: empty map"+minElemFMB (I i k (Just v) E m r) = v+minElemFMB (I i k Nothing E (FMB' m) r) = minElemFMB m+minElemFMB (I i k mv l m r) = minElemFMB l++minElem (FM (Just v) fmb) = v+minElem (FM Nothing fmb) = minElemFMB fmb+++minElemWithKeyFMB :: ([k] -> [k]) -> FMB k a -> ([k],a)+minElemWithKeyFMB kf E = error $ moduleName++".minElemWithKey: empty map"+minElemWithKeyFMB kf (I i k (Just v) E m r) = (kf [k],v)+minElemWithKeyFMB kf (I i k Nothing E (FMB' m) r) = minElemWithKeyFMB (kf . (k:)) m+minElemWithKeyFMB kf (I i k mv l m r) = minElemWithKeyFMB kf l++minElemWithKey :: FM k a -> ([k],a)+minElemWithKey (FM (Just v) fmb) = ([],v)+minElemWithKey (FM Nothing fmb) = minElemWithKeyFMB id fmb++deleteMin :: Ord k => FM k a -> FM k a+deleteMin = deleteMinUsingMinView++unsafeInsertMin :: Ord k => [k] -> a -> FM k a -> FM k a+unsafeInsertMin = insert++maxViewFMB :: Monad m => FMB k a -> (FMB k a -> FM k a) -> m (a, FM k a)+maxViewFMB (I i k (Just v) l (FMB' E) E) f = return (v, f l)+--maxViewFMB (I i k (Just v) l (FMB' E) E) f = return (v, f (I i k Nothing l (FMB' E) E))+maxViewFMB (I i k Nothing l (FMB' E) E) f = error $ moduleName++".maxView: bug!"+maxViewFMB (I i k mv l (FMB' m) E) f = maxViewFMB m (\m' -> f (I i k mv l (FMB' m') E))+maxViewFMB (I i k mv l m r) f = maxViewFMB r (\r' -> f (mkVBalancedFMB k mv l m r'))+maxViewFMB E f = error $ moduleName++".maxView: bug!"++maxView :: Monad m => FM k a -> m (a, FM k a)+maxView (FM Nothing E) = fail $ moduleName++".maxView: empty map"+maxView (FM (Just v) E) = return (v,FM Nothing E)+maxView (FM mv fmb) = maxViewFMB fmb (FM mv)+++maxViewWithKeyFMB :: Monad m => FMB k a -> ([k] -> [k]) -> (FMB k a -> FM k a) -> m (([k],a),FM k a)+maxViewWithKeyFMB (I i k (Just v) l (FMB' E) E) kf f = return ((kf [k],v),f l)+maxViewWithKeyFMB (I i k Nothing l (FMB' E) E) kf f = error $ moduleName++".maxViewWithKey: bug!"+maxViewWithKeyFMB (I i k mv l (FMB' m) E) kf f = maxViewWithKeyFMB m (kf . (k:))+ (\m' -> f (I i k mv l (FMB' m') E))+maxViewWithKeyFMB (I i k mv l m r) kf f = maxViewWithKeyFMB r kf+ (\r' -> f (mkVBalancedFMB k mv l m r'))+maxViewWithKeyFMB E kf f = error $ moduleName++".maxViewWithKey: bug!"+++maxViewWithKey :: Monad m => FM k a -> m (([k],a), FM k a)+maxViewWithKey (FM Nothing E) = fail $ moduleName++".maxViewWithKey: empty map"+maxViewWithKey (FM (Just v) E) = return (([],v),FM Nothing E)+maxViewWithKey (FM mv fmb) = maxViewWithKeyFMB fmb id (FM mv)++++maxElemFMB :: FMB k a -> a+maxElemFMB (I i k (Just v) l (FMB' E) E) = v+maxElemFMB (I i k Nothing l (FMB' E) E) = error $ moduleName++".maxElem: bug!"+maxElemFMB (I i k mv l (FMB' m) E) = maxElemFMB m+maxElemFMB (I i k mv l m r) = maxElemFMB r+maxElemFMB E = error $ moduleName++".maxElem: bug!"++maxElem :: FM k a -> a+maxElem (FM (Just v) E) = v+maxElem (FM Nothing E) = error $ moduleName++".maxElem: empty map"+maxElem (FM _ fmb) = maxElemFMB fmb++maxElemWithKeyFMB :: FMB k a -> ([k] -> [k]) -> ([k],a)+maxElemWithKeyFMB (I i k (Just v) l (FMB' E) E) kf = (kf [k],v)+maxElemWithKeyFMB (I i k Nothing l (FMB' E) E) kf = error $ moduleName++".maxElemWithKey: bug!"+maxElemWithKeyFMB (I i k mv l (FMB' m) E) kf = maxElemWithKeyFMB m (kf . (k:))+maxElemWithKeyFMB (I i k mv l m r) kf = maxElemWithKeyFMB r kf+maxElemWithKeyFMB E kf = error $ moduleName++".maxElemWithKey: bug!"+++maxElemWithKey :: FM k a -> ([k],a)+maxElemWithKey (FM (Just v) E) = ([],v)+maxElemWithKey (FM Nothing E) = error $ moduleName++".maxElemWithKey: empty map"+maxElemWithKey (FM _ fmb) = maxElemWithKeyFMB fmb id+++deleteMax :: Ord k => FM k a -> FM k a+deleteMax = deleteMaxUsingMaxView++unsafeInsertMax :: Ord k => [k] -> a -> FM k a -> FM k a+unsafeInsertMax = insert++unsafeFromOrdSeq :: (Ord k,S.Sequence seq) => seq ([k],a) -> FM k a+unsafeFromOrdSeq = fromSeq++unsafeAppend :: Ord k => FM k a -> FM k a -> FM k a+unsafeAppend = union++-- FIXME this doesn't respect the structural invariant... why??+{-+unsafeAppend (FM (Just v) fmb1) (FM Nothing fmb2) = FM (Just v) (appendFMB fmb1 fmb2)+unsafeAppend (FM Nothing fmb1) (FM mv fmb2) = FM mv (appendFMB fmb1 fmb2)+unsafeAppend (FM (Just _) _) (FM (Just _) _) = error $ moduleName++".unsafeAppend: bug!"+-}++filterL_FMB :: Ord k => (k -> Maybe a -> FMB k a -> FMB k a) -> k -> [k] -> FMB k a -> FMB k a+filterL_FMB f k ks E = E+filterL_FMB f k ks (I i key mv l (FMB' m) r)+ | key < k = mkVBalancedFMB key mv l (FMB' m) (filterL_FMB f k ks r)+ | key > k = filterL_FMB f k ks l+ | otherwise = case ks of+ [] -> f k mv l+ (k':ks') -> mkVBalancedFMB key mv l (FMB' (filterL_FMB f k' ks' m)) E++filterLT :: Ord k => [k] -> FM k a -> FM k a+filterLT [] _ = FM Nothing E+filterLT (k:ks) (FM mv fmb) = FM mv (filterL_FMB (\k mv l -> l) k ks fmb)++filterLE :: Ord k => [k] -> FM k a -> FM k a+filterLE [] (FM mv _) = FM mv E+filterLE (k:ks) (FM mv fmb) = FM mv (filterL_FMB (\k mv l -> mkVBalancedFMB k mv l (FMB' E) E) k ks fmb)++++filterG_FMB :: Ord k => (k -> Maybe a -> FMB k a -> FMB k a -> FMB k a) -> k -> [k] -> FMB k a -> FMB k a+filterG_FMB f k ks E = E+filterG_FMB f k ks (I i key mv l (FMB' m) r)+ | key < k = filterG_FMB f k ks r+ | key > k = mkVBalancedFMB key mv (filterG_FMB f k ks l) (FMB' m) r+ | otherwise = case ks of+ [] -> f k mv m r+ (k':ks') -> mkVBalancedFMB key Nothing E (FMB' (filterG_FMB f k' ks' m)) r++filterGT :: Ord k => [k] -> FM k a -> FM k a+filterGT [] (FM _ fmb) = FM Nothing fmb+filterGT (k:ks) (FM mv fmb) = FM Nothing (filterG_FMB (\k mv m r -> mkVBalancedFMB k Nothing E (FMB' m) r) k ks fmb)++filterGE :: Ord k => [k] -> FM k a -> FM k a+filterGE [] fm = fm+filterGE (k:ks) (FM mv fmb) = FM Nothing (filterG_FMB (\k mv m r -> mkVBalancedFMB k mv E (FMB' m) r) k ks fmb)++--FIXME do better...+partitionLT_GE :: Ord k => [k] -> FM k a -> (FM k a,FM k a)+partitionLT_GE ks fm = (filterLT ks fm, filterGE ks fm)++partitionLE_GT :: Ord k => [k] -> FM k a -> (FM k a,FM k a)+partitionLE_GT ks fm = (filterLE ks fm, filterGT ks fm)++partitionLT_GT :: Ord k => [k] -> FM k a -> (FM k a,FM k a)+partitionLT_GT ks fm = (filterLT ks fm, filterGT ks fm)++toOrdSeq = toOrdSeqUsingFoldrWithKey++-- instance declarations++instance Ord k => A.AssocX (FM k) [k] where+ {empty = empty; singleton = singleton; fromSeq = fromSeq; insert = insert; + insertSeq = insertSeq; union = union; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq; + null = null; size = size; member = member; count = count; + lookup = lookup; lookupM = lookupM; lookupAll = lookupAll; + lookupAndDelete = lookupAndDelete; lookupAndDeleteM = lookupAndDeleteM;+ lookupAndDeleteAll = lookupAndDeleteAll;+ lookupWithDefault = lookupWithDefault; adjust = adjust; + adjustAll = adjustAll; adjustOrInsert = adjustOrInsert;+ adjustAllOrInsert = adjustAllOrInsert;+ adjustOrDelete = adjustOrDelete; adjustOrDeleteAll = adjustOrDeleteAll;+ fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; elements = elements;+ strict = strict; strictWith = strictWith;+ structuralInvariant = structuralInvariant; instanceName m = moduleName}++instance Ord k => A.Assoc (FM k) [k] where+ {toSeq = toSeq; keys = keys; mapWithKey = mapWithKey; + foldWithKey = foldWithKey; foldWithKey' = foldWithKey';+ filterWithKey = filterWithKey; + partitionWithKey = partitionWithKey}++instance Ord k => A.FiniteMapX (FM k) [k] where+ {fromSeqWith = fromSeqWith; fromSeqWithKey = fromSeqWithKey; + insertWith = insertWith; insertWithKey = insertWithKey; + insertSeqWith = insertSeqWith; insertSeqWithKey = insertSeqWithKey; + unionl = unionl; unionr = unionr; unionWith = unionWith; + unionSeqWith = unionSeqWith; intersectionWith = intersectionWith; + difference = difference; properSubset = properSubset; subset = subset;+ properSubmapBy = properSubmapBy; submapBy = submapBy;+ sameMapBy = sameMapBy}++instance Ord k => A.FiniteMap (FM k) [k] where+ {unionWithKey = unionWithKey; unionSeqWithKey = unionSeqWithKey; + intersectionWithKey = intersectionWithKey}++instance Ord k => A.OrdAssocX (FM k) [k] where+ {minView = minView; minElem = minElem; deleteMin = deleteMin;+ unsafeInsertMin = unsafeInsertMin; maxView = maxView; maxElem = maxElem;+ deleteMax = deleteMax; unsafeInsertMax = unsafeInsertMax;+ foldr = foldr; foldr' = foldr'; foldl = foldl; foldl' = foldl';+ foldr1 = foldr1; foldr1' = foldr1'; foldl1 = foldl1; foldl1' = foldl1';+ unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend;+ filterLT = filterLT; filterLE = filterLE; filterGT = filterGT;+ filterGE = filterGE; partitionLT_GE = partitionLT_GE;+ partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance Ord k => A.OrdAssoc (FM k) [k] where+ {minViewWithKey = minViewWithKey; minElemWithKey = minElemWithKey;+ maxViewWithKey = maxViewWithKey; maxElemWithKey = maxElemWithKey;+ foldrWithKey = foldrWithKey; foldrWithKey' = foldrWithKey';+ foldlWithKey = foldlWithKey; foldlWithKey' = foldlWithKey';+ toOrdSeq = toOrdSeq}++instance Ord k => A.OrdFiniteMapX (FM k) [k] +instance Ord k => A.OrdFiniteMap (FM k) [k]+++instance Ord k => Functor (FM k) where+ fmap = map++instance (Ord k, Show k, Show a) => Show (FM k a) where+ showsPrec = showsPrecUsingToList++instance (Ord k, Read k, Read a) => Read (FM k a) where+ readsPrec = readsPrecUsingFromList++instance (Ord k, Eq a) => Eq (FM k a) where+ (==) = sameMap++instance (Ord k, Ord a) => Ord (FM k a) where+ compare = compareUsingToOrdList++--+-- Test code follows+--++keyInvariantFMB :: Ord k => (k -> Bool) -> FMB k a -> Bool+keyInvariantFMB p E = True+keyInvariantFMB p (I _ k _ l _ r)+ = p k+ && keyInvariantFMB p l+ && keyInvariantFMB p r++actualSizeFMB :: FMB k a -> Int+actualSizeFMB E = 0+actualSizeFMB (I _ _ _ l _ r) = 1 + actualSizeFMB l + actualSizeFMB r++structuralInvariantFMB :: Ord k => FMB k a -> Bool+structuralInvariantFMB E = True+structuralInvariantFMB fmb@(I size k _ l (FMB' m) r)+ = structuralInvariantFMB l+ && structuralInvariantFMB m+ && structuralInvariantFMB r+ && keyInvariantFMB (<k) l+ && keyInvariantFMB (>k) r+ && actualSizeFMB fmb == size+ && (sizel + sizer < 2+ || (sizel <= balance * sizer && sizer <= balance * sizel))+ where+ sizel = sizeFMB l+ sizer = sizeFMB r++structuralInvariant :: Ord k => FM k a -> Bool+structuralInvariant (FM k fmb) = structuralInvariantFMB fmb+++instance (Ord k,Arbitrary k,Arbitrary a) => Arbitrary (FM k a) where+ arbitrary = do xs <- arbitrary+ return (Prelude.foldr (uncurry insert) empty xs)++ coarbitrary (FM x fmb) = coarbitrary_maybe x . coarbitrary_fmb fmb+++coarbitrary_maybe Nothing = variant 0+coarbitrary_maybe (Just x) = variant 1 . coarbitrary x++coarbitrary_fmb E = variant 0+coarbitrary_fmb (I _ k x l (FMB' m) r) =+ variant 1 . coarbitrary k . coarbitrary_maybe x .+ coarbitrary_fmb l . coarbitrary_fmb m . coarbitrary_fmb r++instance Ord k => Monoid (FM k a) where+ mempty = empty+ mappend = union+ mconcat = unionSeq+
+ src/Data/Edison/Coll/Defaults.hs view
@@ -0,0 +1,244 @@+-- |+-- Module : Data.Edison.Coll.Defaults+-- Copyright : Copyright (c) 1998 Chris Okasaki+-- License : MIT; see COPYRIGHT file for terms and conditions+--+-- Maintainer : robdockins AT fastmail DOT fm+-- Stability : internal (unstable)+-- Portability : GHC / Hugs (MPTC and FD)+--+-- This module provides default implementations of many of the collection methods. The functions+-- in this module are used to fill out collection implementations and are not intended to be+-- used directly by end users.++module Data.Edison.Coll.Defaults where++import Prelude hiding (null,foldr,foldl,foldr1,foldl1,lookup,filter)+import Control.Monad.Identity++import Data.Edison.Coll+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Seq.ListSeq as L+import Data.Edison.Seq.Defaults (tokenMatch,maybeParens)++insertSeqUsingUnion :: (CollX c a,S.Sequence seq) => seq a -> c -> c+insertSeqUsingUnion xs c = union (fromSeq xs) c++insertSeqUsingFoldr :: (CollX c a,S.Sequence seq) => seq a -> c -> c+insertSeqUsingFoldr xs c = S.foldr insert c xs++memberUsingFold :: Coll c a => c -> a -> Bool+memberUsingFold h x = fold (\y ans -> (x == y) || ans) False h++countUsingMember :: SetX c a => a -> c -> Int+countUsingMember x xs = if member x xs then 1 else 0++lookupAllUsingLookupM :: (Set c a,S.Sequence seq) => a -> c -> seq a+lookupAllUsingLookupM x xs =+ case lookupM x xs of+ Nothing -> S.empty+ Just y -> S.singleton y++deleteSeqUsingDelete :: (CollX c a,S.Sequence seq) => seq a -> c -> c+deleteSeqUsingDelete xs c = S.foldr delete c xs++unionSeqUsingFoldl :: (CollX c a,S.Sequence seq) => seq c -> c+unionSeqUsingFoldl = S.foldl union empty++unionSeqUsingFoldl' :: (CollX c a,S.Sequence seq) => seq c -> c+unionSeqUsingFoldl' = S.foldl' union empty++unionSeqUsingReduce :: (CollX c a,S.Sequence seq) => seq c -> c+unionSeqUsingReduce = S.reducel union empty++fromSeqUsingFoldr :: (CollX c a,S.Sequence seq) => seq a -> c+fromSeqUsingFoldr = S.foldr insert empty++fromSeqUsingUnionSeq :: (CollX c a,S.Sequence seq) => seq a -> c+fromSeqUsingUnionSeq = unionList . S.foldl singleCons []+ where singleCons xs x = S.lcons (singleton x) xs++toSeqUsingFold :: (Coll c a,S.Sequence seq) => c -> seq a+toSeqUsingFold = fold S.lcons S.empty++unsafeInsertMaxUsingUnsafeAppend :: OrdCollX c a => a -> c -> c+unsafeInsertMaxUsingUnsafeAppend x c = unsafeAppend c (singleton x)++toOrdSeqUsingFoldr :: (OrdColl c a,S.Sequence seq) => c -> seq a+toOrdSeqUsingFoldr = foldr S.lcons S.empty++unsafeFromOrdSeqUsingUnsafeInsertMin :: + (OrdCollX c a,S.Sequence seq) => seq a -> c+unsafeFromOrdSeqUsingUnsafeInsertMin = S.foldr unsafeInsertMin empty++disjointUsingToOrdList :: OrdColl c a => c -> c -> Bool+disjointUsingToOrdList xs ys = disj (toOrdList xs) (toOrdList ys)+ where disj a@(x:xs) b@(y:ys) =+ case compare x y of+ LT -> disj xs b+ EQ -> False+ GT -> disj a ys+ disj _ _ = True++intersectWitnessUsingToOrdList ::+ (OrdColl c a, Monad m) => c -> c -> m (a,a)+intersectWitnessUsingToOrdList xs ys = witness (toOrdList xs) (toOrdList ys)+ where witness a@(x:xs) b@(y:ys) =+ case compare x y of+ LT -> witness xs b+ EQ -> return (x, y)+ GT -> witness a ys+ -- XXX+ witness _ _ = fail $ instanceName xs ++ ".intersect: failed"++lookupUsingLookupM :: Coll c a => a -> c -> a+lookupUsingLookupM x ys = runIdentity (lookupM x ys)++lookupUsingLookupAll :: Coll c a => a -> c -> a+lookupUsingLookupAll x ys =+ case lookupAll x ys of+ (y:_) -> y+ [] -> error $ instanceName ys ++ ".lookup: lookup failed"++lookupMUsingLookupAll :: (Coll c a, Monad m) => a -> c -> m a+lookupMUsingLookupAll x ys =+ case lookupAll x ys of+ (y:_) -> return y+ [] -> fail $ instanceName ys ++ ".lookupM: lookup failed"++lookupWithDefaultUsingLookupAll :: Coll c a => a -> a -> c -> a+lookupWithDefaultUsingLookupAll dflt x ys =+ case lookupAll x ys of+ (y:_) -> y+ [] -> dflt++lookupWithDefaultUsingLookupM :: Coll c a => a -> a -> c -> a+lookupWithDefaultUsingLookupM dflt x ys =+ case lookupM x ys of+ Just y -> y+ Nothing -> dflt++deleteMaxUsingMaxView :: OrdColl c a => c -> c+deleteMaxUsingMaxView c =+ case maxView c of+ Just (_,c') -> c'+ Nothing -> c++fromSeqWithUsingInsertWith :: (Set c a,S.Sequence seq) => (a -> a -> a) -> seq a -> c+fromSeqWithUsingInsertWith c = S.foldr (insertWith c) empty++insertUsingInsertWith :: Set c a => a -> c -> c+insertUsingInsertWith = insertWith (\x y -> x)++unionUsingUnionWith :: Set c a => c -> c -> c+unionUsingUnionWith = unionWith (\x y -> x)++filterUsingOrdLists :: OrdColl c a => (a -> Bool) -> c -> c+filterUsingOrdLists p = unsafeFromOrdList . L.filter p . toOrdList++partitionUsingOrdLists :: OrdColl c a => (a -> Bool) -> c -> (c,c)+partitionUsingOrdLists p xs = (unsafeFromOrdList ys,unsafeFromOrdList zs)+ where (ys,zs) = L.partition p (toOrdList xs)++intersectionUsingIntersectionWith :: Set c a => c -> c -> c+intersectionUsingIntersectionWith = intersectionWith (\x y -> x)++differenceUsingOrdLists :: OrdSet c a => c -> c -> c+differenceUsingOrdLists xs ys = unsafeFromOrdList (diff (toOrdList xs) (toOrdList ys))+ where diff a@(x:xs) b@(y:ys) =+ case compare x y of+ LT -> x : diff xs b+ EQ -> diff xs ys+ GT -> diff a ys+ diff a _ = a++symmetricDifferenceUsingDifference :: SetX c a => c -> c -> c+symmetricDifferenceUsingDifference xs ys = union (difference xs ys) (difference ys xs)++properSubsetUsingOrdLists :: OrdSet c a => c -> c -> Bool+properSubsetUsingOrdLists xs ys = properSubsetOnOrdLists (toOrdList xs) (toOrdList ys)++subsetUsingOrdLists :: OrdSet c a => c -> c -> Bool+subsetUsingOrdLists xs ys = subsetOnOrdLists (toOrdList xs) (toOrdList ys)++properSubsetOnOrdLists [] [] = False+properSubsetOnOrdLists [] (_:_) = True+properSubsetOnOrdLists (_:_) [] = False+properSubsetOnOrdLists a@(x:xs) (y:ys) =+ case compare x y of+ LT -> False+ EQ -> properSubsetOnOrdLists xs ys+ GT -> subsetOnOrdLists a ys++subsetOnOrdLists [] _ = True+subsetOnOrdLists (_:_) [] = False+subsetOnOrdLists a@(x:xs) (y:ys) =+ case compare x y of+ LT -> False+ EQ -> subsetOnOrdLists xs ys+ GT -> subsetOnOrdLists a ys++insertSeqWithUsingInsertWith :: (Set c a,S.Sequence seq) => (a -> a -> a) -> seq a -> c -> c+insertSeqWithUsingInsertWith c xs s = S.foldr (insertWith c) s xs++unionlUsingUnionWith :: Set c a => c -> c -> c+unionlUsingUnionWith xs ys = unionWith (\x y -> x) xs ys++unionrUsingUnionWith :: Set c a => c -> c -> c+unionrUsingUnionWith xs ys = unionWith (\x y -> y) xs ys++unionWithUsingOrdLists :: OrdSet c a => (a -> a -> a) -> c -> c -> c+unionWithUsingOrdLists c xs ys = unsafeFromOrdList (merge (toOrdList xs) (toOrdList ys))+ where merge a@(x:xs) b@(y:ys) =+ case compare x y of+ LT -> x : merge xs b+ EQ -> c x y : merge xs ys+ GT -> y : merge a ys+ merge a@(x:xs) [] = a+ merge [] b = b++unionSeqWithUsingReducer :: (Set c a,S.Sequence seq) => (a -> a -> a) -> seq c -> c+unionSeqWithUsingReducer c = S.reducer (unionWith c) empty++intersectionWithUsingOrdLists :: OrdSet c a => (a -> a -> a) -> c -> c -> c+intersectionWithUsingOrdLists c xs ys = unsafeFromOrdList (inter (toOrdList xs) (toOrdList ys))+ where inter a@(x:xs) b@(y:ys) =+ case compare x y of+ LT -> inter xs b+ EQ -> c x y : inter xs ys+ GT -> inter a ys+ inter _ _ = []+++unsafeMapMonotonicUsingFoldr :: (OrdColl cin a, OrdCollX cout b) => (a -> b) -> (cin -> cout)+unsafeMapMonotonicUsingFoldr f xs = foldr (unsafeInsertMin . f) empty xs++showsPrecUsingToList :: (Coll c a,Show a) => Int -> c -> ShowS+showsPrecUsingToList i xs rest+ | i == 0 = concat [ instanceName xs,".fromSeq ",showsPrec 10 (toList xs) rest]+ | otherwise = concat ["(",instanceName xs,".fromSeq ",showsPrec 10 (toList xs) (')':rest)]++readsPrecUsingFromList :: (Coll c a, Read a) => Int -> ReadS c+readsPrecUsingFromList i xs =+ let result = maybeParens p xs+ p xs = tokenMatch ((instanceName x)++".fromSeq") xs+ >>= readsPrec 10+ >>= \(l,rest) -> return (fromList l,rest)++ -- play games with the typechecker so we don't have to use+ -- extensions for scoped type variables+ ~[(x,_)] = result++ in result++compareUsingToOrdList :: OrdColl c a => c -> c -> Ordering+compareUsingToOrdList xs ys = cmp (toOrdList xs) (toOrdList ys)+ where+ cmp [] [] = EQ+ cmp [] _ = LT+ cmp _ [] = GT+ cmp (x:xs) (y:ys) =+ case compare x y of+ EQ -> cmp xs ys+ c -> c+
+ src/Data/Edison/Coll/EnumSet.hs view
@@ -0,0 +1,798 @@+-----------------------------------------------------------------------------+-- |+-- Module : Data.Edison.Coll.EnumSet+-- Copyright : (c) David F. Place 2006+-- License : BSD+--+-- Maintainer : robdockins AT fastmail DOT fm+-- Stability : stable+-- Portability : GHC, Hugs (MPTC and FD)+--+-- An efficient implementation of sets over small enumerations.+-- The implementation of 'EnumSet' is based on bit-wise operations.+--+-- For this implementation to work as expected at type @A@, there are a number+-- of preconditions on the @Eq@, @Enum@ and @Ord@ instances.+--+-- The @Enum A@ instance must create a bijection between the elements of type @A@ and+-- a finite subset of the naturals [0,1,2,3....]. As a corollary we must have:+--+-- > forall x y::A, fromEnum x == fromEnum y <==> x is indistinguishable from y+--+-- Also, the number of distinct elements of @A@ must be less than or equal+-- to the number of bits in @Word@.+--+-- The @Enum A@ instance must be consistent with the @Eq A@ instance. +-- That is, we must have:+--+-- > forall x y::A, x == y <==> toEnum x == toEnum y +--+-- Additionally, for operations that require an @Ord A@ context, we require that+-- toEnum be monotonic with respect to comparison. That is, we must have:+--+-- > forall x y::A, x < y <==> toEnum x < toEnum y+--+-- Derived @Eq@, @Ord@ and @Enum@ instances will fulfill these conditions, if+-- the enumerated type has sufficently few constructors.++{-+Copyright (c) 2006, David F. Place+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ +* Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++* Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.++* Neither the name of David F. Place nor the names of its+ contributors may be used to endorse or promote products derived from+ this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+-} ++module Data.Edison.Coll.EnumSet (+ -- * Set type+ Set ++ -- * CollX operations+ , empty+ , singleton+ , fromSeq+ , insert+ , insertSeq+ , union+ , unionSeq+ , delete+ , deleteAll+ , deleteSeq+ , null+ , size+ , member+ , count+ , strict++ -- * OrdCollX operations+ , deleteMin+ , deleteMax+ , unsafeInsertMin+ , unsafeInsertMax+ , unsafeFromOrdSeq+ , unsafeAppend+ , filterLT+ , filterLE+ , filterGT+ , filterGE+ , partitionLT_GE+ , partitionLE_GT+ , partitionLT_GT++ -- * SetX operations+ , intersection+ , difference+ , symmetricDifference+ , properSubset+ , subset++ -- * Coll operations+ , toSeq+ , lookup+ , lookupM+ , lookupAll+ , lookupWithDefault+ , fold, fold', fold1, fold1'+ , filter+ , partition+ , strictWith++ -- * OrdColl operations+ , minView+ , minElem+ , maxView+ , maxElem+ , foldr, foldr', foldl, foldl'+ , foldr1, foldr1', foldl1, foldl1'+ , toOrdSeq+ , unsafeMapMonotonic++ -- * Set operations+ , fromSeqWith+ , insertWith+ , insertSeqWith+ , unionl+ , unionr+ , unionWith+ , unionSeqWith+ , intersectionWith++ -- * Bonus operations+ , map+ , setCoerce+ , complement+ , toBits+ , fromBits++ -- * Documenation+ , moduleName+) where++import qualified Prelude+import Prelude hiding (filter,foldl,foldr,null,map,lookup,foldl1,foldr1)+import qualified Data.Bits as Bits+import Data.Bits hiding (complement)+import Data.Word+import Data.Monoid (Monoid(..))+import Data.Array++import Data.Edison.Prelude+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Coll as C+import qualified Data.Edison.Seq.ListSeq as L+import Data.Edison.Coll.Defaults+import Test.QuickCheck hiding (check)++moduleName = "Data.Edison.Coll.EnumSet"++{--------------------------------------------------------------------+ Sets are bit strings of width wordLength.+--------------------------------------------------------------------}+-- | A set of values @a@ implemented as bitwise operations. Useful+-- for members of class Enum with no more elements than there are bits +-- in @Word@.+newtype Set a = Set Word deriving (Eq)++wordLength :: Int+wordLength = bitSize (0::Word)++check :: String -> Int -> Int +check msg x + | x < wordLength = x+ | otherwise = error $ "EnumSet."++msg++": element beyond word size."+++-- no interesting structural invariants+structuralInvariant :: Set a -> Bool+structuralInvariant = const True+++----------------------------------------------------+-- bit twiddly magic++countBits :: Word -> Int+countBits w = w `seq` bitcount 0 w++bitcount :: Int -> Word -> Int+bitcount a 0 = a+bitcount a x = a `seq` bitcount (a+1) (x .&. (x-1))++-- stolen from http://aggregate.org/MAGIC/+lsb :: Word -> Int+lsb x = countBits ((x-1) .&. (Bits.complement x))++msb :: Word -> Int+msb x0 = let+ x1 = x0 .|. (x0 `shiftR` 1)+ x2 = x1 .|. (x1 `shiftR` 2)+ x3 = x2 .|. (x2 `shiftR` 4)+ x4 = x3 .|. (x3 `shiftR` 8)+ x5 = x4 .|. (x4 `shiftR` 16)+ in countBits x5 - 1+++lowMask :: Int -> Word+lowMask x = bit x - 1++highMask :: Int -> Word+highMask x = Bits.complement (lowMask x)++{--------------------------------------------------------------------+ Query+--------------------------------------------------------------------}+-- | /O(1)/. Is this the empty set?+null :: Set a -> Bool+null (Set 0) = True+null _ = False++-- | /O(1)/. The number of elements in the set.+size :: Set a -> Int+size (Set w) = countBits w++-- | /O(1)/. Is the element in the set?+member :: (Eq a, Enum a) => a -> Set a -> Bool+member x (Set w) = testBit w $ fromEnum x++count :: (Eq a, Enum a) => a -> Set a -> Int+count = countUsingMember++lookup :: (Eq a, Enum a) => a -> Set a -> a+lookup = lookupUsingLookupAll++lookupM :: (Eq a, Enum a, Monad m) => a -> Set a -> m a+lookupM x s+ | member x s = return x+ | otherwise = fail (moduleName++".lookupM: lookup failed")++lookupAll :: (Eq a, Enum a, S.Sequence s) => a -> Set a -> s a+lookupAll = lookupAllUsingLookupM++lookupWithDefault :: (Eq a, Enum a) => a -> a -> Set a -> a+lookupWithDefault = lookupWithDefaultUsingLookupM++{--------------------------------------------------------------------+ Construction+--------------------------------------------------------------------}+-- | /O(1)/. The empty set.+empty :: Set a+empty = Set 0++-- | /O(1)/. Create a singleton set.+singleton :: (Eq a, Enum a) => a -> Set a+singleton x =+ Set $ setBit 0 $ check "singleton" $ fromEnum x++{--------------------------------------------------------------------+ Insertion, Deletion+--------------------------------------------------------------------}+-- | /O(1)/. Insert an element in a set.+-- If the set already contains an element equal to the given value,+-- it is replaced with the new value.+insert :: (Eq a, Enum a) => a -> Set a -> Set a+insert x (Set w) =+ Set $ setBit w $ check "insert" $ fromEnum x++-- given the preconditions, we can just ignore the combining function+insertWith :: (Eq a, Enum a) => (a -> a -> a) -> a -> Set a -> Set a+insertWith f x (Set w) =+ Set $ setBit w $ check "insertWith" $ fromEnum x++-- | /O(1)/. Delete an element from a set.+delete :: (Eq a, Enum a) => a -> Set a -> Set a+delete x (Set w) = + Set $ clearBit w $ fromEnum x++deleteAll :: (Eq a, Enum a) => a -> Set a -> Set a+deleteAll = delete++deleteSeq :: (Eq a, Enum a, S.Sequence s) => s a -> Set a -> Set a+deleteSeq = deleteSeqUsingDelete++{--------------------------------------------------------------------+ Subset+--------------------------------------------------------------------}+-- | /O(1)/. Is this a proper subset? (ie. a subset but not equal).+properSubset :: Set a -> Set a -> Bool+properSubset x y = (x /= y) && (subset x y)++-- | /O(1)/. Is this a subset?+-- @(s1 `subset` s2)@ tells whether @s1@ is a subset of @s2@.+subset :: Set a -> Set a -> Bool+subset x y = (x `union` y) == y++{--------------------------------------------------------------------+ Minimal, Maximal+--------------------------------------------------------------------}++-- | /O(1)/. The minimal element of a set.+minElem :: (Enum a) => Set a -> a+minElem (Set w) + | w == 0 = error $ moduleName++".minElem: empty set"+ | otherwise = toEnum $ lsb w++-- | /O(1)/. The maximal element of a set.+maxElem :: (Enum a) => Set a -> a+maxElem (Set w)+ | w == 0 = error $ moduleName++".maxElem: empty set"+ | otherwise = toEnum $ msb w++-- | /O(1)/. Delete the minimal element.+deleteMin :: (Enum a) => Set a -> Set a+deleteMin (Set w) + | w == 0 = empty+ | otherwise = Set $ clearBit w $ lsb w++-- | /O(1)/. Delete the maximal element.+deleteMax :: (Enum a) => Set a -> Set a+deleteMax (Set w)+ | w == 0 = empty+ | otherwise = Set $ clearBit w $ msb w++minView :: (Enum a, Monad m) => Set a -> m (a, Set a)+minView (Set w)+ | w == 0 = fail (moduleName++".minView: empty set")+ | otherwise = let i = lsb w in return (toEnum i,Set $ clearBit w i)++maxView :: (Enum a, Monad m) => Set a -> m (a, Set a)+maxView (Set w)+ | w == 0 = fail (moduleName++".maxView: empty set")+ | otherwise = let i = msb w in return (toEnum i, Set $ clearBit w i)++unsafeInsertMin :: (Ord a, Enum a) => a -> Set a -> Set a+unsafeInsertMin = insert++unsafeInsertMax :: (Ord a, Enum a) => a -> Set a -> Set a+unsafeInsertMax = insert++unsafeAppend :: (Ord a, Enum a) => Set a -> Set a -> Set a+unsafeAppend = union++unsafeFromOrdSeq :: (Ord a, Enum a, S.Sequence s) => s a -> Set a+unsafeFromOrdSeq = fromSeq++filterLT :: (Ord a, Enum a) => a -> Set a -> Set a+filterLT x (Set w) = Set (w .&. lowMask (fromEnum x))++filterLE :: (Ord a, Enum a) => a -> Set a -> Set a+filterLE x (Set w) = Set (w .&. lowMask (fromEnum x + 1))++filterGT :: (Ord a, Enum a) => a -> Set a -> Set a+filterGT x (Set w) = Set (w .&. highMask (fromEnum x + 1))++filterGE :: (Ord a, Enum a) => a -> Set a -> Set a+filterGE x (Set w) = Set (w .&. highMask (fromEnum x))++partitionLT_GE :: (Ord a, Enum a) => a -> Set a -> (Set a, Set a)+partitionLT_GE x s = (filterLT x s,filterGE x s)++partitionLE_GT :: (Ord a, Enum a) => a -> Set a -> (Set a, Set a)+partitionLE_GT x s = (filterLE x s,filterGT x s)++partitionLT_GT :: (Ord a, Enum a) => a -> Set a -> (Set a, Set a)+partitionLT_GT x s = (filterLT x s,filterGT x s)+++{--------------------------------------------------------------------+ Union. +--------------------------------------------------------------------}+-- | The union of a list of sets: (@'unions' == 'foldl' 'union' 'empty'@).+unionSeq :: (Eq a, Enum a, S.Sequence s) => s (Set a) -> Set a+unionSeq = unionSeqUsingFoldl'++-- | /O(1)/. The union of two sets.+union :: Set a -> Set a -> Set a+union (Set x) (Set y) = Set $ x .|. y++unionl :: Set a -> Set a -> Set a+unionl = union++unionr :: Set a -> Set a -> Set a+unionr = union++-- given the preconditions, we can just ignore the combining function+unionWith :: (a -> a -> a) -> Set a -> Set a -> Set a+unionWith f = union++unionSeqWith :: (Eq a, Enum a, S.Sequence s) => (a -> a -> a) -> s (Set a) -> Set a+unionSeqWith f = unionSeq++{--------------------------------------------------------------------+ Difference+--------------------------------------------------------------------}+-- | /O(1)/. Difference of two sets. +difference :: Set a -> Set a -> Set a+difference (Set x) (Set y) = Set $ (x .|. y) `xor` y++symmetricDifference :: Set a -> Set a -> Set a+symmetricDifference (Set x) (Set y) = Set $ x `xor` y++{--------------------------------------------------------------------+ Intersection+--------------------------------------------------------------------}+-- | /O(1)/. The intersection of two sets.+intersection :: Set a -> Set a -> Set a+intersection (Set x) (Set y) = Set $ x .&. y++intersectionWith :: (a -> a -> a) -> Set a -> Set a -> Set a+intersectionWith f = intersection++{--------------------------------------------------------------------+ Complement+--------------------------------------------------------------------}+-- | /O(1)/. The complement of a set with its universe set. @complement@ can be used+-- with bounded types for which the universe set+-- will be automatically created.+complement :: (Eq a, Bounded a, Enum a) => Set a -> Set a+complement x = symmetricDifference u x+ where u = (fromSeq [minBound .. maxBound]) `asTypeOf` x++{--------------------------------------------------------------------+ Filter and partition+--------------------------------------------------------------------}+-- | /O(n)/. Filter all elements that satisfy the predicate.+filter :: (Eq a, Enum a) => (a -> Bool) -> Set a -> Set a+filter p (Set w) = Set $ foldlBits' f 0 w+ where + f z i + | p $ toEnum i = setBit z i+ | otherwise = z++-- | /O(n)/. Partition the set into two sets, one with all elements that satisfy+-- the predicate and one with all elements that don't satisfy the predicate.+-- See also 'split'.+partition :: (Eq a, Enum a) => (a -> Bool) -> Set a -> (Set a,Set a)+partition p (Set w) = (Set yay,Set nay)+ where + (yay,nay) = foldlBits' f (0,0) w+ f (x,y) i+ | p $ toEnum i = (setBit x i,y)+ | otherwise = (x,setBit y i)+++{----------------------------------------------------------------------+ Map+----------------------------------------------------------------------}+-- | /O(n)/. +-- @'map' f s@ is the set obtained by applying @f@ to each element of @s@.+-- +-- It's worth noting that the size of the result may be smaller if,+-- for some @(x,y)@, @x \/= y && f x == f y@+map :: (Enum a,Enum b) => (a -> b) -> Set a -> Set b+map f0 (Set w) = Set $ foldlBits' f 0 w+ where+ f z i = setBit z $ check "map" $ fromEnum $ f0 (toEnum i)++unsafeMapMonotonic :: (Enum a) => (a -> a) -> Set a -> Set a+unsafeMapMonotonic = map++-- | /O(1)/ Changes the type of the elements in the set without changing+-- the representation. Equivalant to @map (toEnum . fromEnum)@, and+-- to @(fromBits . toBits)@. This method is operationally a no-op.+setCoerce :: (Enum a, Enum b) => Set a -> Set b+setCoerce (Set w) = Set w++-- | /O(1)/ Get the underlying bit-encoded representation.+-- This method is operationally a no-op.+toBits :: Set a -> Word+toBits (Set w) = w++-- | /O(1)/ Create an EnumSet from a bit-encoded representation.+-- This method is operationally a no-op.+fromBits :: Word -> Set a+fromBits w = Set w+++{--------------------------------------------------------------------+ Fold+--------------------------------------------------------------------}++fold :: (Eq a, Enum a) => (a -> c -> c) -> c -> Set a -> c+fold f z (Set w) = foldrBits folder z w+ where folder i z = f (toEnum i) z++fold' :: (Eq a, Enum a) => (a -> c -> c) -> c -> Set a -> c+fold' f z (Set w) = foldrBits' folder z w+ where folder i z = f (toEnum i) z++fold1 :: (Eq a, Enum a) => (a -> a -> a) -> Set a -> a+fold1 f (Set 0) = error (moduleName++".fold1: empty set")+fold1 f (Set w) = foldrBits folder (toEnum max) (clearBit w max)+ where+ max = msb w+ folder i z = f (toEnum i) z++fold1' :: (Eq a, Enum a) => (a -> a -> a) -> Set a -> a+fold1' f (Set 0) = error (moduleName++".fold1': empty set")+fold1' f (Set w) = foldrBits folder (toEnum max) (clearBit w max)+ where+ max = msb w+ folder i z = f (toEnum i) z++foldr :: (Ord a, Enum a) => (a -> b -> b) -> b -> Set a -> b+foldr f z (Set w) = foldrBits folder z w+ where folder i z = f (toEnum i) z++foldr' :: (Ord a, Enum a) => (a -> b -> b) -> b -> Set a -> b+foldr' f z (Set w) = foldrBits' folder z w+ where folder i z = f (toEnum i) z++foldr1 :: (Ord a, Enum a) => (a -> a -> a) -> Set a -> a+foldr1 f (Set 0) = error (moduleName++".foldr1: empty set")+foldr1 f (Set w) = foldrBits folder (toEnum max) (clearBit w max)+ where+ max = msb w+ folder i z = f (toEnum i) z++foldr1' :: (Ord a, Enum a) => (a -> a -> a) -> Set a -> a+foldr1' f (Set 0) = error (moduleName++".foldr1': empty set")+foldr1' f (Set w) = foldrBits folder (toEnum max) (clearBit w max)+ where+ max = msb w+ folder i z = f (toEnum i) z++foldl :: (Ord a, Enum a) => (c -> a -> c) -> c -> Set a -> c+foldl f z (Set w) = foldlBits folder z w+ where folder z i = f z (toEnum i)++foldl' :: (Ord a, Enum a) => (c -> a -> c) -> c -> Set a -> c+foldl' f z (Set w) = foldlBits' folder z w+ where folder z i = f z (toEnum i)++foldl1 :: (Ord a, Enum a) => (a -> a -> a) -> Set a -> a+foldl1 f (Set 0) = error (moduleName++".foldl1: empty set")+foldl1 f (Set w) = foldlBits folder (toEnum min) (clearBit w min)+ where+ min = lsb w+ folder z i = f z (toEnum i)++foldl1' :: (Ord a, Enum a) => (a -> a -> a) -> Set a -> a+foldl1' f (Set 0) = error (moduleName++".foldl1': empty set")+foldl1' f (Set w) = foldlBits' folder (toEnum min) (clearBit w min)+ where+ min = lsb w+ folder z i = f z (toEnum i)++{--------------------------------------------------------------------+ Lists +--------------------------------------------------------------------}+fromSeq :: (Eq a, Enum a, S.Sequence s) => s a -> Set a+fromSeq xs = Set $ S.fold' f 0 xs+ where f x z = setBit z $ check "fromSeq" $ fromEnum x++fromOrdSeq :: (Ord a, Enum a, S.Sequence s) => s a -> Set a+fromOrdSeq = fromSeq++insertSeq :: (Eq a, Enum a, S.Sequence s) => s a -> Set a -> Set a+insertSeq = insertSeqUsingUnion++-- given the preconditions, we can just ignore the combining function+insertSeqWith :: (Eq a, Enum a, S.Sequence s) => (a -> a -> a) -> s a -> Set a -> Set a+insertSeqWith f = insertSeq++toSeq :: (Eq a, Enum a, S.Sequence s) => Set a -> s a+toSeq (Set w) = foldrBits f S.empty w+ where f i z = S.lcons (toEnum i) z++toOrdSeq :: (Ord a, Enum a, S.Sequence s) => Set a -> s a+toOrdSeq = toSeq++fromSeqWith :: (Eq a, Enum a, S.Sequence s) => (a -> a -> a) -> s a -> Set a+fromSeqWith = fromSeqWithUsingInsertWith +++{--------------------------------------------------------------------+ Split+--------------------------------------------------------------------}+{-+splitMember :: (Ord a, Enum a) => a -> Set a -> (Set a,Bool,Set a)+splitMember x (Set w) = (Set lesser,isMember,Set greater)+ where+ (lesser,isMember,greater) = foldrBits f (0,False,0) w+ f i (lesser,isMember,greater) =+ case compare (toEnum i) x of+ GT -> (lesser,isMember,setBit greater i)+ LT -> (setBit lesser i,isMember,greater)+ EQ -> (lesser,True,greater)+-}+++{----------------------------------------------------------------+ Strictness enhancement+----------------------------------------------------------------}++strict :: Set a -> Set a+strict s@(Set w) = w `seq` s++strictWith :: (a -> b) -> Set a -> Set a+strictWith f s@(Set w) = w `seq` s++{--------------------------------------------------------------------+ Utility functions. +--------------------------------------------------------------------}++foldrBits :: (Int -> a -> a) -> a -> Word -> a+foldrBits f z w = foldrBits_aux f z 0 w++foldrBits_aux :: (Int -> a -> a) -> a -> Int -> Word -> a+foldrBits_aux f z i 0 = z+foldrBits_aux f z i w+ | i `seq` w `seq` False = undefined+ | otherwise =+ case w .&. 0x0F of+ 0x00 -> a+ 0x01 -> f i $ a+ 0x02 -> f (i+1) $ a+ 0x03 -> f i $ f (i+1) $ a+ 0x04 -> f (i+2) $ a+ 0x05 -> f i $ f (i+2) $ a+ 0x06 -> f (i+1) $ f (i+2) $ a+ 0x07 -> f i $ f (i+1) $ f (i+2) $ a+ 0x08 -> f (i+3) $ a+ 0x09 -> f i $ f (i+3) $ a+ 0x0A -> f (i+1) $ f (i+3) $ a+ 0x0B -> f i $ f (i+1) $ f (i+3) $ a+ 0x0C -> f (i+2) $ f (i+3) $ a+ 0x0D -> f i $ f (i+2) $ f (i+3) $ a+ 0x0E -> f (i+1) $ f (i+2) $ f (i+3) $ a+ 0x0F -> f i $ f (i+1) $ f (i+2) $ f (i+3) $ a+ _ -> error "bug in foldrBits_aux"++ where a = foldrBits_aux f z (i+4) (Bits.shiftR w 4)+++foldrBits' :: (Int -> a -> a) -> a -> Word -> a+foldrBits' f z w = foldrBits_aux' f z 0 w++foldrBits_aux' :: (Int -> a -> a) -> a -> Int -> Word -> a+foldrBits_aux' f z i 0 = z+foldrBits_aux' f z i w+ | i `seq` w `seq` False = undefined+ | otherwise =+ case w .&. 0x0F of+ 0x00 -> a+ 0x01 -> f i $! a+ 0x02 -> f (i+1) $! a+ 0x03 -> f i $! f (i+1) $! a+ 0x04 -> f (i+2) $! a+ 0x05 -> f i $! f (i+2) $! a+ 0x06 -> f (i+1) $! f (i+2) $! a+ 0x07 -> f i $! f (i+1) $! f (i+2) $! a+ 0x08 -> f (i+3) $! a+ 0x09 -> f i $! f (i+3) $! a+ 0x0A -> f (i+1) $! f (i+3) $! a+ 0x0B -> f i $! f (i+1) $! f (i+3) $! a+ 0x0C -> f (i+2) $! f (i+3) $! a+ 0x0D -> f i $! f (i+2) $! f (i+3) $! a+ 0x0E -> f (i+1) $! f (i+2) $! f (i+3) $! a+ 0x0F -> f i $! f (i+1) $! f (i+2) $! f (i+3) $! a+ _ -> error "bug in foldrBits_aux'"++ where a = foldrBits_aux' f z (i+4) (Bits.shiftR w 4)+++foldlBits :: (a -> Int -> a) -> a -> Word -> a+foldlBits f z w = foldlBits_aux f z 0 w++foldlBits_aux :: (a -> Int -> a) -> a -> Int -> Word -> a+foldlBits_aux f z i 0 = z+foldlBits_aux f z i w+ | i `seq` w `seq` False = undefined+ | otherwise =+ case w .&. 0x0F of+ 0x00 -> a $ z+ 0x01 -> a $ f z i+ 0x02 -> a $ f z (i+1)+ 0x03 -> a $ f (f z i) (i+1)+ 0x04 -> a $ f z (i+2)+ 0x05 -> a $ f (f z i) (i+2)+ 0x06 -> a $ f (f z (i+1)) (i+2)+ 0x07 -> a $ f (f (f z i) (i+1)) (i+2)+ 0x08 -> a $ f z (i+3)+ 0x09 -> a $ f (f z i) (i+3)+ 0x0A -> a $ f (f z (i+1)) (i+3)+ 0x0B -> a $ f (f (f z i) (i+1)) (i+3)+ 0x0C -> a $ f (f z (i+2)) (i+3)+ 0x0D -> a $ f (f (f z i) (i+2)) (i+3)+ 0x0E -> a $ f (f (f z (i+1)) (i+2)) (i+3)+ 0x0F -> a $ f (f (f (f z i) (i+1)) (i+2)) (i+3)+ _ -> error "bug in foldlBits_aux"++ where a z = foldlBits_aux f z (i+4) (Bits.shiftR w 4)++foldlBits' :: (a -> Int -> a) -> a -> Word -> a+foldlBits' f z w = foldlBits_aux' (\x i -> x `seq` f x i) z 0 w++foldlBits_aux' :: (a -> Int -> a) -> a -> Int -> Word -> a+foldlBits_aux' f z i 0 = z+foldlBits_aux' f z i w+ | i `seq` w `seq` False = undefined+ | otherwise =+ case w .&. 0x0F of+ 0x00 -> a $! z+ 0x01 -> a $! f z i+ 0x02 -> a $! f z (i+1)+ 0x03 -> a $! f (f z i) (i+1)+ 0x04 -> a $! f z (i+2)+ 0x05 -> a $! f (f z i) (i+2)+ 0x06 -> a $! f (f z (i+1)) (i+2)+ 0x07 -> a $! f (f (f z i) (i+1)) (i+2)+ 0x08 -> a $! f z (i+3)+ 0x09 -> a $! f (f z i) (i+3)+ 0x0A -> a $! f (f z (i+1)) (i+3)+ 0x0B -> a $! f (f (f z i) (i+1)) (i+3)+ 0x0C -> a $! f (f z (i+2)) (i+3)+ 0x0D -> a $! f (f (f z i) (i+2)) (i+3)+ 0x0E -> a $! f (f (f z (i+1)) (i+2)) (i+3)+ 0x0F -> a $! f (f (f (f z i) (i+1)) (i+2)) (i+3)+ _ -> error "bug in foldlBits_aux"++ where a z = foldlBits_aux' f z (i+4) (Bits.shiftR w 4)++instance (Eq a, Enum a) => C.CollX (Set a) a where+ {singleton = singleton; fromSeq = fromSeq; insert = insert;+ insertSeq = insertSeq; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq;+ null = null; size = size; member = member; count = count;+ strict = strict;+ structuralInvariant = structuralInvariant; instanceName c = moduleName}++instance (Ord a, Enum a) => C.OrdCollX (Set a) a where+ {deleteMin = deleteMin; deleteMax = deleteMax; + unsafeInsertMin = unsafeInsertMin; unsafeInsertMax = unsafeInsertMax; + unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend; + filterLT = filterLT; filterLE = filterLE; filterGT = filterGT; + filterGE = filterGE; partitionLT_GE = partitionLT_GE; + partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance (Eq a, Enum a) => C.SetX (Set a) a where+ {intersection = intersection; difference = difference;+ symmetricDifference = symmetricDifference;+ properSubset = properSubset; subset = subset}++instance (Eq a, Enum a) => C.Coll (Set a) a where+ {toSeq = toSeq; lookup = lookup; lookupM = lookupM; + lookupAll = lookupAll; lookupWithDefault = lookupWithDefault; + fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; strictWith = strictWith}++instance (Ord a, Enum a) => C.OrdColl (Set a) a where+ {minView = minView; minElem = minElem; maxView = maxView; + maxElem = maxElem; foldr = foldr; foldr' = foldr'; + foldl = foldl; foldl' = foldl'; foldr1 = foldr1; foldr1' = foldr1';+ foldl1 = foldl1; foldl1' = foldl1'; toOrdSeq = toOrdSeq;+ unsafeMapMonotonic = unsafeMapMonotonic}++instance (Eq a, Enum a) => C.Set (Set a) a where+ {fromSeqWith = fromSeqWith; insertWith = insertWith; + insertSeqWith = insertSeqWith; unionl = unionl; unionr = unionr;+ unionWith = unionWith; unionSeqWith = unionSeqWith;+ intersectionWith = intersectionWith}++instance (Ord a, Enum a) => C.OrdSetX (Set a) a+instance (Ord a, Enum a) => C.OrdSet (Set a) a++instance (Eq a, Enum a, Show a) => Show (Set a) where+ showsPrec = showsPrecUsingToList++instance (Eq a, Enum a, Read a) => Read (Set a) where+ readsPrec = readsPrecUsingFromList++instance (Eq a, Enum a, Arbitrary a) => Arbitrary (Set a) where+ arbitrary = do (w::Int) <- arbitrary+ return (Set (fromIntegral w))++ coarbitrary (Set w) = coarbitrary (fromIntegral w :: Int)++instance (Eq a, Enum a) => Monoid (Set a) where+ mempty = empty+ mappend = union+ mconcat = unionSeq++instance (Ord a, Enum a) => Ord (Set a) where+ compare = compareUsingToOrdList
+ src/Data/Edison/Coll/LazyPairingHeap.hs view
@@ -0,0 +1,562 @@+-- |+-- Module : Data.Edison.Coll.LazyPairingHeap+-- 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)+--+-- Lazy Paring Heaps+--+-- /References:/+--+-- * Chris Okasaki. /Purely Functional Data Structures/. 1998.+-- Section 6.5.++module Data.Edison.Coll.LazyPairingHeap (+ -- * Type of pairing heaps+ Heap, -- instance of Coll/CollX, OrdColl/OrdCollX++ -- * CollX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,strict,structuralInvariant,++ -- * Coll operations+ toSeq, lookup, lookupM, lookupAll, lookupWithDefault, fold, fold',+ fold1, fold1', filter, partition, strictWith,++ -- * OrdCollX operations+ deleteMin,deleteMax,unsafeInsertMin,unsafeInsertMax,unsafeFromOrdSeq,+ unsafeAppend,filterLT,filterLE,filterGT,filterGE,partitionLT_GE,+ partitionLE_GT,partitionLT_GT,++ -- * OrdColl operations+ minView,minElem,maxView,maxElem,foldr,foldr',foldl,foldl',+ foldr1,foldr1',foldl1,foldl1',toOrdSeq,+ unsafeMapMonotonic,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,foldr,foldl,foldr1,foldl1,lookup,filter)+import Data.Edison.Prelude+import qualified Data.Edison.Coll as C ( CollX(..), OrdCollX(..),+ Coll(..), OrdColl(..), toOrdList )+import qualified Data.Edison.Seq as S+import Data.Edison.Coll.Defaults+import Data.List(sort)+import Data.Monoid+import Control.Monad+import Test.QuickCheck++moduleName = "Data.Edison.Coll.LazyPairingHeap"+++data Heap a = E + | H1 a (Heap a)+ | H2 a !(Heap a) (Heap a)+++-- Invariants: +-- * left child of H2 not empty+structuralInvariant :: Heap a -> Bool+structuralInvariant E = True+structuralInvariant (H1 _ h) = structuralInvariant h+structuralInvariant (H2 _ E _) = False+structuralInvariant (H2 _ l r) = structuralInvariant l && structuralInvariant r++-- second arg is not empty+-- not used!+link E h = h+link (H1 x b) a = H2 x a b+link (H2 x a b) a' = H1 x (union (union a a') b)++makeH2 x E xs = H1 x xs+makeH2 x h xs = H2 x h xs++empty :: Heap a+empty = E++singleton :: a -> Heap a+singleton x = H1 x E++insert :: Ord a => a -> Heap a -> Heap a+insert x E = H1 x E+insert x h@(H1 y b)+ | x <= y = H1 x h+ | otherwise = H2 y (H1 x E) b+insert x h@(H2 y a b)+ | x <= y = H1 x h+ | otherwise = H1 y (union (insert x a) b)++union :: Ord a => Heap a -> Heap a -> Heap a+union E h = h+union hx@(H1 x xs) E = hx+union hx@(H1 x xs) hy@(H1 y ys)+ | x <= y = H2 x hy xs+ | otherwise = H2 y hx ys+union hx@(H1 x xs) hy@(H2 y a ys)+ | x <= y = H2 x hy xs+ | otherwise = H1 y (union (union hx a) ys)+union hx@(H2 x a xs) E = hx+union hx@(H2 x a xs) hy@(H1 y ys)+ | x <= y = H1 x (union (union hy a) xs)+ | otherwise = H2 y hx ys+union hx@(H2 x a xs) hy@(H2 y b ys)+ | x <= y = H1 x (union (union hy a) xs)+ | otherwise = H1 y (union (union hx b) ys)++delete :: Ord a => a -> Heap a -> Heap a+delete y h = case del h of Just h' -> h'+ Nothing -> h+ where del E = Nothing+ del (H1 x xs) =+ case compare x y of+ LT -> case del xs of+ Just xs -> Just (H1 x xs)+ Nothing -> Nothing+ EQ -> Just xs+ GT -> Nothing+ del (H2 x a xs) =+ case compare x y of+ LT -> case del a of+ Just a' -> Just (makeH2 x a' xs)+ Nothing -> case del xs of+ Just xs' -> Just (H2 x a xs')+ Nothing -> Nothing+ EQ -> Just (union a xs)+ GT -> Nothing++deleteAll :: Ord a => a -> Heap a -> Heap a+deleteAll y E = E+deleteAll y h@(H1 x xs) =+ case compare x y of+ LT -> H1 x (deleteAll y xs)+ EQ -> deleteAll y xs+ GT -> h+deleteAll y h@(H2 x a xs) =+ case compare x y of+ LT -> makeH2 x (deleteAll y a) (deleteAll y xs)+ EQ -> union (deleteAll y a) (deleteAll y xs)+ GT -> h++deleteSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a -> Heap a+deleteSeq = delList . sort . S.toList+ where delList [] h = h+ delList (y:ys) h = del y ys h++ del y ys E = E+ del y ys h@(H1 x xs) =+ case compare x y of+ LT -> H1 x (del y ys xs)+ EQ -> delList ys xs+ GT -> delList ys h+ del y ys h@(H2 x a xs) =+ case compare x y of+ LT -> H1 x (del y ys (union a xs))+ EQ -> delList ys (union a xs)+ GT -> delList ys h+ {-+ could write the two GT cases as+ delList (dropWhile (< x) ys) h+ but this is only a win if we expect many of the ys+ to be missing from the tree. However, we expect most+ of the ys to be present.+ -}++null :: Heap a -> Bool+null E = True+null _ = False++size :: Heap a -> Int+size E = 0+size (H1 x xs) = 1 + size xs+size (H2 x h xs) = 1 + size h + size xs++member :: Ord a => a -> Heap a -> Bool+member x E = False+member x (H1 y ys) =+ case compare x y of+ LT -> False+ EQ -> True+ GT -> member x ys+member x (H2 y h ys) =+ case compare x y of+ LT -> False+ EQ -> True+ GT -> member x h || member x ys++count :: Ord a => a -> Heap a -> Int+count x E = 0+count x (H1 y ys) =+ case compare x y of+ LT -> 0+ EQ -> 1 + count x ys+ GT -> count x ys+count x (H2 y h ys) =+ case compare x y of+ LT -> 0+ EQ -> 1 + count x h + count x ys+ GT -> count x h + count x ys++deleteMin :: Ord a => Heap a -> Heap a+deleteMin E = E+deleteMin (H1 x xs) = xs+deleteMin (H2 x h xs) = union h xs++unsafeInsertMin :: Ord a => a -> Heap a -> Heap a+unsafeInsertMin = H1++unsafeInsertMax :: Ord a => a -> Heap a -> Heap a+unsafeInsertMax x E = H1 x E+unsafeInsertMax x (H1 y ys) = H2 y (H1 x E) ys+unsafeInsertMax x (H2 y h ys) = H1 y (union (unsafeInsertMax x h) ys)++unsafeAppend :: Ord a => Heap a -> Heap a -> Heap a+unsafeAppend h E = h+unsafeAppend E h = h+unsafeAppend (H1 x xs) h = H2 x h xs+unsafeAppend (H2 x a xs) h = H1 x (union (unsafeAppend a h) xs)++filterLT :: Ord a => a -> Heap a -> Heap a+filterLT y E = E+filterLT y (H1 x xs)+ | x < y = H1 x (filterLT y xs)+ | otherwise = E+filterLT y (H2 x h xs)+ | x < y = makeH2 x (filterLT y h) (filterLT y xs)+ | otherwise = E++filterLE :: Ord a => a -> Heap a -> Heap a+filterLE y E = E+filterLE y (H1 x xs)+ | x <= y = H1 x (filterLE y xs)+ | otherwise = E+filterLE y (H2 x h xs)+ | x <= y = makeH2 x (filterLE y h) (filterLE y xs)+ | otherwise = E++filterGT :: Ord a => a -> Heap a -> Heap a+filterGT y h = fgt h E+ where fgt E rest = rest+ fgt h@(H1 x xs) rest+ | x > y = union h rest+ | otherwise = fgt xs rest+ fgt h@(H2 x a xs) rest+ | x > y = union h rest+ | otherwise = fgt a (fgt xs rest)++filterGE :: Ord a => a -> Heap a -> Heap a+filterGE y h = fge h E+ where fge E rest = rest+ fge h@(H1 x xs) rest+ | x >= y = union h rest+ | otherwise = fge xs rest+ fge h@(H2 x a xs) rest+ | x >= y = union h rest+ | otherwise = fge a (fge xs rest)++partitionLT_GE :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLT_GE y E = (E,E)+partitionLT_GE y h@(H1 x xs)+ | x < y = let (xs',xs'') = partitionLT_GE y xs+ in (H1 x xs',xs'')+ | otherwise = (E, h)+partitionLT_GE y h@(H2 x a xs)+ | x < y = let (a',a'') = partitionLT_GE y a+ (xs',xs'') = partitionLT_GE y xs+ in (makeH2 x a' xs',union a'' xs'')+ | otherwise = (E, h)++partitionLE_GT :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLE_GT y E = (E,E)+partitionLE_GT y h@(H1 x xs)+ | x <= y = let (xs',xs'') = partitionLE_GT y xs+ in (H1 x xs',xs'')+ | otherwise = (E, h)+partitionLE_GT y h@(H2 x a xs)+ | x <= y = let (a',a'') = partitionLE_GT y a+ (xs',xs'') = partitionLE_GT y xs+ in (makeH2 x a' xs',union a'' xs'')+ | otherwise = (E, h)++partitionLT_GT :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLT_GT y E = (E,E)+partitionLT_GT y h@(H1 x xs) =+ case compare x y of+ LT -> let (xs',xs'') = partitionLT_GT y xs+ in (H1 x xs',xs'')+ EQ -> (E, filterGT y xs)+ GT -> (E, h)+partitionLT_GT y h@(H2 x a xs) =+ case compare x y of+ LT -> let (a',a'') = partitionLT_GT y a+ (xs',xs'') = partitionLT_GT y xs+ in (makeH2 x a' xs',union a'' xs'')+ EQ -> (E, union (filterGT y a) (filterGT y xs))+ GT -> (E, h)++toSeq :: S.Sequence seq => Heap a -> seq a+toSeq h = tol h S.empty+ where tol E rest = rest+ tol (H1 x xs) rest = S.lcons x (tol xs rest)+ tol (H2 x h xs) rest = S.lcons x (tol h (tol xs rest))++fold :: (a -> b -> b) -> b -> Heap a -> b+fold f c E = c+fold f c (H1 x xs) = f x (fold f c xs)+fold f c (H2 x h xs) = f x (fold f (fold f c xs) h)++fold' :: (a -> b -> b) -> b -> Heap a -> b+fold' f c E = c+fold' f c (H1 x xs) = c `seq` f x $! (fold' f c xs)+fold' f c (H2 x h xs) = c `seq` f x $! (fold' f (fold' f c xs) h)+++fold1 :: (a -> a -> a) -> Heap a -> a+fold1 f E = error "LazyPairingHeap.fold1: empty heap"+fold1 f (H1 x xs) = fold f x xs+fold1 f (H2 x h xs) = fold f (fold f x xs) h++fold1' :: (a -> a -> a) -> Heap a -> a+fold1' f E = error "LazyPairingHeap.fold1': empty heap"+fold1' f (H1 x xs) = fold' f x xs+fold1' f (H2 x h xs) = fold' f (fold' f x xs) h+++filter :: Ord a => (a -> Bool) -> Heap a -> Heap a+filter p E = E+filter p (H1 x xs) = if p x then H1 x (filter p xs) else filter p xs+filter p (H2 x h xs) =+ if p x then makeH2 x (filter p h) (filter p xs)+ else union (filter p h) (filter p xs)++partition :: Ord a => (a -> Bool) -> Heap a -> (Heap a, Heap a)+partition p E = (E, E)+partition p (H1 x xs) = if p x then (H1 x xs',xs'') else (xs',H1 x xs'')+ where (xs',xs'') = partition p xs+partition p (H2 x h xs) =+ if p x then (makeH2 x h' xs', union h'' xs'')+ else (union h' xs', makeH2 x h'' xs'')+ where (h',h'') = partition p h+ (xs',xs'') = partition p xs++lookupAll :: (Ord a,S.Sequence seq) => a -> Heap a -> seq a+lookupAll y h = look h S.empty+ where look E rest = rest+ look (H1 x xs) rest =+ case compare x y of+ LT -> look xs rest+ EQ -> S.lcons x (look xs rest)+ GT -> rest+ look (H2 x h xs) rest =+ case compare x y of+ LT -> look h (look xs rest)+ EQ -> S.lcons x (look h (look xs rest))+ GT -> rest++minView :: (Ord a, Monad m) => Heap a -> m (a, Heap a)+minView E = fail "LazyPairingHeap.minView: empty heap"+minView (H1 x xs) = return (x,xs)+minView (H2 x h xs) = return (x,union h xs)++minElem :: Heap a -> a+minElem E = error "LazyPairingHeap.minElem: empty heap"+minElem (H1 x xs) = x+minElem (H2 x h xs) = x++maxView :: (Ord a, Monad m) => Heap a -> m (a, Heap a)+maxView E = fail "LazyPairingHeap.maxView: empty heap"+maxView xs = return (y,xs')+ where (xs', y) = maxView' xs++-- not exported+maxView' (H1 x E) = (E, x)+maxView' (H1 x xs) = (H1 x xs', y)+ where (xs', y) = maxView' xs+maxView' (H2 x a E) = (H1 x a', y)+ where (a', y) = maxView' a+maxView' (H2 x a xs) = + if y > z then (makeH2 x a' xs, y) else (H2 x a xs', z)+ where (a', y) = maxView' a+ (xs', z) = maxView' xs+maxView' E = error "LazyPairingHeap.maxView': bug!"++maxElem :: Ord a => Heap a -> a+maxElem E = error "LazyPairingHeap.maxElem: empty heap"+maxElem (H1 x E) = x+maxElem (H1 x xs) = maxElem xs+maxElem (H2 x h E) = maxElem h+maxElem (H2 x h xs) = max (maxElem h) (maxElem xs)++foldr :: Ord a => (a -> b -> b) -> b -> Heap a -> b+foldr f c E = c+foldr f c (H1 x xs) = f x (foldr f c xs)+foldr f c (H2 x h xs) = f x (foldr f c (union h xs))++foldr' :: Ord a => (a -> b -> b) -> b -> Heap a -> b+foldr' f c E = c+foldr' f c (H1 x xs) = c `seq` f x $! (foldr' f c xs)+foldr' f c (H2 x h xs) = c `seq` f x $! (foldr' f c (union h xs))++foldl :: Ord a => (b -> a -> b) -> b -> Heap a -> b+foldl f c E = c+foldl f c (H1 x xs) = foldl f (f c x) xs+foldl f c (H2 x h xs) = foldl f (f c x) (union h xs)++foldl' :: Ord a => (b -> a -> b) -> b -> Heap a -> b+foldl' f c E = c+foldl' f c (H1 x xs) = c `seq` foldl' f (f c x) xs+foldl' f c (H2 x h xs) = c `seq` foldl' f (f c x) (union h xs)++foldr1 :: Ord a => (a -> a -> a) -> Heap a -> a+foldr1 f E = error "LazyPairingHeap.foldr1: empty heap"+foldr1 f (H1 x E) = x+foldr1 f (H1 x xs) = f x (foldr1 f xs)+foldr1 f (H2 x h xs) = f x (foldr1 f (union h xs))++foldr1' :: Ord a => (a -> a -> a) -> Heap a -> a+foldr1' f E = error "LazyPairingHeap.foldr1': empty heap"+foldr1' f (H1 x E) = x+foldr1' f (H1 x xs) = f x $! (foldr1' f xs)+foldr1' f (H2 x h xs) = f x $! (foldr1' f (union h xs))++foldl1 :: Ord a => (a -> a -> a) -> Heap a -> a+foldl1 f E = error "LazyPairingHeap.foldl1: empty heap"+foldl1 f (H1 x xs) = foldl f x xs+foldl1 f (H2 x h xs) = foldl f x (union h xs)++foldl1' :: Ord a => (a -> a -> a) -> Heap a -> a+foldl1' f E = error "LazyPairingHeap.foldl1': empty heap"+foldl1' f (H1 x xs) = foldl' f x xs+foldl1' f (H2 x h xs) = foldl' f x (union h xs)++unsafeMapMonotonic :: (Ord a,Ord b) => (a -> b) -> Heap a -> Heap b+unsafeMapMonotonic = mapm+ where mapm f E = E+ mapm f (H1 x xs) = H1 (f x) (mapm f xs)+ mapm f (H2 x h xs) = H2 (f x) (mapm f h) (mapm f xs)+++strict :: Heap a -> Heap a+strict h@E = h+strict h@(H1 x xs) = strict xs `seq` h+strict h@(H2 x h' xs) = strict h' `seq` strict xs `seq` h++strictWith :: (a -> b) -> Heap a -> Heap a+strictWith f h@E = h+strictWith f h@(H1 x xs) = f x `seq` strictWith f xs `seq` h+strictWith f h@(H2 x h' xs) = f x `seq` strictWith f h' `seq` strictWith f xs `seq` h+++-- the remaining functions all use default definitions++fromSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a+fromSeq = fromSeqUsingFoldr++insertSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a -> Heap a+insertSeq = insertSeqUsingFoldr++unionSeq :: (Ord a,S.Sequence seq) => seq (Heap a) -> Heap a+unionSeq = unionSeqUsingFoldl++unsafeFromOrdSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a+unsafeFromOrdSeq = unsafeFromOrdSeqUsingUnsafeInsertMin++deleteMax :: Ord a => Heap a -> Heap a+deleteMax = deleteMaxUsingMaxView++lookup :: Ord a => a -> Heap a -> a+lookup = lookupUsingLookupAll++lookupM :: (Ord a, Monad m) => a -> Heap a -> m a+lookupM = lookupMUsingLookupAll++lookupWithDefault :: Ord a => a -> a -> Heap a -> a+lookupWithDefault = lookupWithDefaultUsingLookupAll++toOrdSeq :: (Ord a,S.Sequence seq) => Heap a -> seq a+toOrdSeq = toOrdSeqUsingFoldr++-- instance declarations++instance Ord a => C.CollX (Heap a) a where+ {singleton = singleton; fromSeq = fromSeq; insert = insert;+ insertSeq = insertSeq; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq;+ null = null; size = size; member = member; count = count;+ strict = strict;+ structuralInvariant = structuralInvariant; instanceName c = moduleName}++instance Ord a => C.OrdCollX (Heap a) a where+ {deleteMin = deleteMin; deleteMax = deleteMax; + unsafeInsertMin = unsafeInsertMin; unsafeInsertMax = unsafeInsertMax; + unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend; + filterLT = filterLT; filterLE = filterLE; filterGT = filterGT; + filterGE = filterGE; partitionLT_GE = partitionLT_GE; + partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance Ord a => C.Coll (Heap a) a where+ {toSeq = toSeq; lookup = lookup; lookupM = lookupM; + lookupAll = lookupAll; lookupWithDefault = lookupWithDefault; + fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; strictWith = strictWith}++instance Ord a => C.OrdColl (Heap a) a where+ {minView = minView; minElem = minElem; maxView = maxView; + maxElem = maxElem; foldr = foldr; foldr' = foldr'; + foldl = foldl; foldl' = foldl'; foldr1 = foldr1;+ foldr1' = foldr1'; foldl1 = foldl1; foldl1' = foldl1';+ toOrdSeq = toOrdSeq; unsafeMapMonotonic = unsafeMapMonotonic}++instance Ord a => Eq (Heap a) where+ xs == ys = C.toOrdList xs == C.toOrdList ys++instance (Ord a, Show a) => Show (Heap a) where+ showsPrec = showsPrecUsingToList++instance (Ord a, Read a) => Read (Heap a) where+ readsPrec = readsPrecUsingFromList++instance (Ord a, Arbitrary a) => Arbitrary (Heap a) where+ arbitrary = sized (\n -> arbTree n)+ where arbTree 0 = return E+ arbTree n =+ frequency [(1, return E),+ (2, liftM2 sift1 arbitrary (arbTree (n - 1))),+ (3, liftM3 sift arbitrary (arbTree (n `div` 4))+ (arbTree (n `div` 2)))]++ sift x E a = sift1 x a+ sift x a E = let H1 x' a' = sift1 x a in H2 x' a' E+ sift x a b+ | x <= ma && x <= mb = H2 x a b+ | ma < x && ma <= mb = H2 ma (siftInto x a) b+ | otherwise = H2 mb a (siftInto x b)+ where ma = minElem a+ mb = minElem b++ sift1 x E = H1 x E+ sift1 x a + | x <= ma = H1 x a+ | otherwise = H1 ma (siftInto x a)+ where ma = minElem a++ siftInto x (H1 _ a) = sift1 x a+ siftInto x (H2 _ a b) = sift x a b+ siftInto x E = error "LazyPairingHeap.arbitrary: bug!"++ coarbitrary E = variant 0+ coarbitrary (H1 x a) = variant 1 . coarbitrary x . coarbitrary a+ coarbitrary (H2 x a b) =+ variant 2 . coarbitrary x . coarbitrary a . coarbitrary b++instance (Ord a) => Monoid (Heap a) where+ mempty = empty+ mappend = union+ mconcat = unionSeq++instance (Ord a) => Ord (Heap a) where+ compare = compareUsingToOrdList
+ src/Data/Edison/Coll/LeftistHeap.hs view
@@ -0,0 +1,489 @@+-- |+-- Module : Data.Edison.Coll.LeftistHeap+-- 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)+--+-- Leftist Heaps+--+-- /References:/+--+-- * Chris Okasaki. /Purely Functional Data Structures/. 1998. Section 3.1.++module Data.Edison.Coll.LeftistHeap (+ -- * Type of leftist heaps+ Heap, -- instance of Coll/CollX, OrdColl/OrdCollX++ -- * CollX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,strict,structuralInvariant,++ -- * Coll operations+ toSeq, lookup, lookupM, lookupAll, lookupWithDefault, fold, fold',+ fold1, fold1', filter, partition, strictWith,++ -- * OrdCollX operations+ deleteMin,deleteMax,unsafeInsertMin,unsafeInsertMax,unsafeFromOrdSeq,+ unsafeAppend,filterLT,filterLE,filterGT,filterGE,partitionLT_GE,+ partitionLE_GT,partitionLT_GT,++ -- * OrdColl operations+ minView,minElem,maxView,maxElem,foldr,foldr',foldl,foldl',+ foldr1,foldr1',foldl1,foldl1',toOrdSeq,+ unsafeMapMonotonic,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,foldr,foldl,foldr1,foldl1,lookup,filter)+import Data.Edison.Prelude+import qualified Data.Edison.Coll as C ( CollX(..), OrdCollX(..), Coll(..), OrdColl(..), + unionList, toOrdList )+import qualified Data.Edison.Seq as S+import Data.Edison.Coll.Defaults+import Data.Monoid+import Control.Monad+import Test.QuickCheck++moduleName = "Data.Edison.Coll.LeftistHeap"++data Heap a = E | L !Int !a !(Heap a) !(Heap a)++-- invariants:+-- * Heap ordered+-- * Leftist; the rank of any left node is >= the+-- rank of its right sibling. The rank of a node+-- is the length of its right spine.++structuralInvariant :: Ord a => Heap a -> Bool+structuralInvariant E = True+structuralInvariant t@(L i x l r) =+ i == rank t && isMin x t && checkLeftist t++ where rank E = 0+ rank (L _ _ _ r) = (rank r) + 1++ isMin x E = True+ isMin x (L _ y l r) = x <= y && (isMin y l) && (isMin y r)++ checkLeftist E = True+ checkLeftist t@(L i _ l r) =+ rank l >= rank r && checkLeftist l && checkLeftist r+++node x a E = L 1 x a E+node x E b = L 1 x b E+node x a@(L m _ _ _) b@(L n _ _ _)+ | m <= n = L (m + 1) x b a+ | otherwise = L (n + 1) x a b++{-+Note: when we want to recurse down both sides, and we have a choice,+recursing down the smaller side first will minimize stack usage.++For delete,deleteAll,filter,partition: could compute fringe and reduce+rather that rebuilding with union at every deleted node+-}++empty :: Ord a => Heap a+empty = E++singleton :: Ord a => a -> Heap a+singleton x = L 1 x E E++insert :: Ord a => a -> Heap a -> Heap a+insert x E = L 1 x E E+insert x h@(L m y a b)+ | x <= y = L 1 x h E+ | otherwise = node y a (insert x b)++union :: Ord a => Heap a -> Heap a -> Heap a+union E h = h+union h@(L _ x a b) h' = union' h x a b h'+ where union' h x a b E = h+ union' hx x a b hy@(L _ y c d)+ | x <= y = node x a (union' hy y c d b)+ | otherwise = node y c (union' hx x a b d)++{-+union E h = h+union h E = h+union h1@(L _ x a b) h2@(L _ y c d)+ | x <= y = node x a (union b h2)+ | otherwise = node y c (union h1 d)+ -- ??? optimize to catch fact that h1 or h2 is known to be L case?+-}++delete :: Ord a => a -> Heap a -> Heap a+delete x h = case del h of+ Just h' -> h'+ Nothing -> h+ where del (L _ y a b) =+ case compare x y of+ LT -> Nothing+ EQ -> Just (union a b)+ GT -> case del b of+ Just b' -> Just (node y a b')+ Nothing -> case del a of+ Just a' -> Just (node y a' b)+ Nothing -> Nothing+ del E = Nothing++deleteAll :: Ord a => a -> Heap a -> Heap a+deleteAll x h@(L _ y a b) =+ case compare x y of+ LT -> h+ EQ -> union (deleteAll x a) (deleteAll x b)+ GT -> node y (deleteAll x a) (deleteAll x b)+deleteAll x E = E++null :: Ord a => Heap a -> Bool+null E = True+null _ = False++size :: Ord a => Heap a -> Int+size h = sz h 0+ where sz E i = i+ sz (L _ _ a b) i = sz a (sz b (i + 1))++member :: Ord a => a -> Heap a -> Bool+member x E = False+member x (L _ y a b) =+ case compare x y of+ LT -> False+ EQ -> True+ GT -> member x b || member x a++count :: Ord a => a -> Heap a -> Int+count x E = 0+count x (L _ y a b) =+ case compare x y of+ LT -> 0+ EQ -> 1 + count x b + count x a+ GT -> count x b + count x a++toSeq :: (Ord a,S.Sequence seq) => Heap a -> seq a+toSeq h = tol h S.empty+ where tol E rest = rest+ tol (L _ x a b) rest = S.lcons x (tol b (tol a rest))++lookupM :: (Ord a, Monad m) => a -> Heap a -> m a+lookupM x E = fail "LeftistHeap.lookupM: XXX"+lookupM x (L _ y a b) =+ case compare x y of+ LT -> fail "LeftistHeap.lookupM: XXX"+ EQ -> return y+ GT -> case lookupM x b `mplus` lookupM x a of+ Nothing -> fail "LeftistHeap.lookupM: XXX"+ Just x -> return x++lookupAll :: (Ord a,S.Sequence seq) => a -> Heap a -> seq a+lookupAll x h = look h S.empty+ where look E ys = ys+ look (L _ y a b) ys =+ case compare x y of+ LT -> ys+ EQ -> S.lcons y (look b (look a ys))+ GT -> look b (look a ys)++fold :: Ord a => (a -> b -> b) -> b -> Heap a -> b+fold f e E = e+fold f e (L _ x a b) = f x (fold f (fold f e a) b)++fold' :: Ord a => (a -> b -> b) -> b -> Heap a -> b+fold' f e E = e+fold' f e (L _ x a b) = e `seq` f x $! (fold' f (fold' f e a) b)++fold1 :: Ord a => (a -> a -> a) -> Heap a -> a+fold1 f E = error "LeftistHeap.fold1: empty collection"+fold1 f (L _ x a b) = fold f (fold f x a) b++fold1' :: Ord a => (a -> a -> a) -> Heap a -> a+fold1' f E = error "LeftistHeap.fold1': empty collection"+fold1' f (L _ x a b) = fold' f (fold' f x a) b+++filter :: Ord a => (a -> Bool) -> Heap a -> Heap a+filter p E = E+filter p (L _ x a b)+ | p x = node x (filter p a) (filter p b)+ | otherwise = union (filter p a) (filter p b)++partition :: Ord a => (a -> Bool) -> Heap a -> (Heap a, Heap a)+partition p E = (E, E)+partition p (L _ x a b)+ | p x = (node x a' b', union a'' b'')+ | otherwise = (union a' b', node x a'' b'')+ where (a', a'') = partition p a+ (b', b'') = partition p b+++deleteMin :: Ord a => Heap a -> Heap a+deleteMin E = E+deleteMin (L _ x a b) = union a b++deleteMax :: Ord a => Heap a -> Heap a+deleteMax h = case maxView h of+ Nothing -> E+ Just (x,h') -> h'++unsafeInsertMin :: Ord a => a -> Heap a -> Heap a+unsafeInsertMin x h = L 1 x h E++unsafeAppend :: Ord a => Heap a -> Heap a -> Heap a+unsafeAppend E h = h+unsafeAppend (L _ y a b) h = node y a (unsafeAppend b h)++filterLT :: Ord a => a -> Heap a -> Heap a+filterLT y (L _ x a b) | x < y = node x (filterLT y a) (filterLT y b)+filterLT y _ = E++filterLE :: Ord a => a -> Heap a -> Heap a+filterLE y (L _ x a b) | x <= y = node x (filterLE y a) (filterLE y b)+filterLE y _ = E++filterGT :: Ord a => a -> Heap a -> Heap a+filterGT y h = C.unionList (collect h [])+ where collect E hs = hs+ collect h@(L _ x a b) hs+ | x > y = h : hs+ | otherwise = collect a (collect b hs)++filterGE :: Ord a => a -> Heap a -> Heap a+filterGE y h = C.unionList (collect h [])+ where collect E hs = hs+ collect h@(L _ x a b) hs+ | x >= y = h : hs+ | otherwise = collect b (collect a hs)++partitionLT_GE :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLT_GE y h = (h', C.unionList hs)+ where (h', hs) = collect h []++ collect E hs = (E, hs)+ collect h@(L _ x a b) hs+ | x >= y = (E, h:hs)+ | otherwise = let (a', hs') = collect a hs+ (b', hs'') = collect b hs'+ in (node x a' b', hs'')++partitionLE_GT :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLE_GT y h = (h', C.unionList hs)+ where (h', hs) = collect h []++ collect E hs = (E, hs)+ collect h@(L _ x a b) hs+ | x > y = (E, h:hs)+ | otherwise = let (a', hs') = collect a hs+ (b', hs'') = collect b hs'+ in (node x a' b', hs'')++partitionLT_GT :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLT_GT y h = (h', C.unionList hs)+ where (h', hs) = collect h []++ collect E hs = (E, hs)+ collect h@(L _ x a b) hs = + case compare x y of+ GT -> (E, h:hs)+ EQ -> let (a', hs') = collect a hs+ (b', hs'') = collect b hs'+ in (union a' b', hs'')+ LT -> let (a', hs') = collect a hs+ (b', hs'') = collect b hs'+ in (node x a' b', hs'')++minView :: (Ord a, Monad m) => Heap a -> m (a, Heap a)+minView E = fail "LeftistHeap.minView: empty collection"+minView (L _ x a b) = return (x, union a b)++minElem :: Ord a => Heap a -> a+minElem E = error "LeftistHeap.minElem: empty collection"+minElem (L _ x a b) = x++maxView :: (Ord a, Monad m) => Heap a -> m (a, Heap a)+maxView E = fail "LeftistHeap.maxView: empty collection"+maxView (L _ x E _) = return (x, E)+maxView (L _ x a E) = return (y, L 1 x a' E)+ where Just (y,a') = maxView a+maxView (L _ x a b)+ | y >= z = return (y, node x a' b)+ | otherwise = return (z, node x a b')+ where Just (y, a') = maxView a+ Just (z, b') = maxView b++-- warning: maxView and maxElem may disagree if root is equal to max!++maxElem :: Ord a => Heap a -> a+maxElem E = error "LeftistHeap.maxElem: empty collection"+maxElem (L _ x E _) = x+maxElem (L _ x a b) = findMax b (findLeaf a)+ where findMax E m = m+ findMax (L _ x E _) m+ | m >= x = m+ | otherwise = x+ findMax (L _ x a b) m = findMax a (findMax b m)++ findLeaf E = error "LeftistHeap.maxElem: bug"+ findLeaf (L _ x E _) = x+ findLeaf (L _ x a b) = findMax b (findLeaf a)++foldr :: Ord a => (a -> b -> b) -> b -> Heap a -> b+foldr f e E = e+foldr f e (L _ x a b) = f x (foldr f e (union a b))++foldr' :: Ord a => (a -> b -> b) -> b -> Heap a -> b+foldr' f e E = e+foldr' f e (L _ x a b) = e `seq` f x $! (foldr' f e (union a b))++foldl :: Ord a => (b -> a -> b) -> b -> Heap a -> b+foldl f e E = e+foldl f e (L _ x a b) = foldl f (f e x) (union a b)++foldl' :: Ord a => (b -> a -> b) -> b -> Heap a -> b+foldl' f e E = e+foldl' f e (L _ x a b) = e `seq` foldl' f (f e x) (union a b)++foldr1 :: Ord a => (a -> a -> a) -> Heap a -> a+foldr1 f E = error "LeftistHeap.foldr1: empty collection"+foldr1 f (L _ x E _) = x+foldr1 f (L _ x a b) = f x (foldr1 f (union a b))++foldr1' :: Ord a => (a -> a -> a) -> Heap a -> a+foldr1' f E = error "LeftistHeap.foldr1': empty collection"+foldr1' f (L _ x E _) = x+foldr1' f (L _ x a b) = f x $! (foldr1' f (union a b))++foldl1 :: Ord a => (a -> a -> a) -> Heap a -> a+foldl1 f E = error "LeftistHeap.foldl1: empty collection"+foldl1 f (L _ x a b) = foldl f x (union a b)++foldl1' :: Ord a => (a -> a -> a) -> Heap a -> a+foldl1' f E = error "LeftistHeap.foldl1: empty collection"+foldl1' f (L _ x a b) = foldl' f x (union a b)++{- ???? -}+unsafeMapMonotonic :: Ord a => (a -> a) -> Heap a -> Heap a+unsafeMapMonotonic f E = E+unsafeMapMonotonic f (L i x a b) =+ L i (f x) (unsafeMapMonotonic f a) (unsafeMapMonotonic f b)+++-- all fields are already fully strict!+strict :: Heap a -> Heap a+strict h = h++strictWith :: (a -> b) -> Heap a -> Heap a+strictWith f h@E = h+strictWith f h@(L i x l r) = f x `seq` strictWith f l `seq` strictWith f r `seq` h++-- the remaining functions all use default definitions++fromSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a+fromSeq = fromSeqUsingUnionSeq++insertSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a -> Heap a+insertSeq = insertSeqUsingUnion++unionSeq :: (Ord a,S.Sequence seq) => seq (Heap a) -> Heap a+unionSeq = unionSeqUsingReduce++deleteSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a -> Heap a+deleteSeq = deleteSeqUsingDelete++lookup :: Ord a => a -> Heap a -> a+lookup = lookupUsingLookupM++lookupWithDefault :: Ord a => a -> a -> Heap a -> a+lookupWithDefault = lookupWithDefaultUsingLookupM++unsafeInsertMax :: Ord a => a -> Heap a -> Heap a+unsafeInsertMax = unsafeInsertMaxUsingUnsafeAppend++unsafeFromOrdSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a+unsafeFromOrdSeq = unsafeFromOrdSeqUsingUnsafeInsertMin++toOrdSeq :: (Ord a,S.Sequence seq) => Heap a -> seq a+toOrdSeq = toOrdSeqUsingFoldr+++-- instance declarations++instance Ord a => C.CollX (Heap a) a where+ {singleton = singleton; fromSeq = fromSeq; insert = insert;+ insertSeq = insertSeq; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq;+ null = null; size = size; member = member; count = count;+ strict = strict;+ structuralInvariant = structuralInvariant; instanceName c = moduleName}++instance Ord a => C.OrdCollX (Heap a) a where+ {deleteMin = deleteMin; deleteMax = deleteMax; + unsafeInsertMin = unsafeInsertMin; unsafeInsertMax = unsafeInsertMax; + unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend; + filterLT = filterLT; filterLE = filterLE; filterGT = filterGT; + filterGE = filterGE; partitionLT_GE = partitionLT_GE; + partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance Ord a => C.Coll (Heap a) a where+ {toSeq = toSeq; lookup = lookup; lookupM = lookupM; + lookupAll = lookupAll; lookupWithDefault = lookupWithDefault; + fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; strictWith = strictWith}++instance Ord a => C.OrdColl (Heap a) a where+ {minView = minView; minElem = minElem; maxView = maxView; + maxElem = maxElem; foldr = foldr; foldr' = foldr';+ foldl = foldl; foldl' = foldl'; foldr1 = foldr1; + foldr1' = foldr1'; foldl1 = foldl1; foldl1' = foldl1';+ toOrdSeq = toOrdSeq; unsafeMapMonotonic = unsafeMapMonotonic}++instance Ord a => Eq (Heap a) where+ xs == ys = C.toOrdList xs == C.toOrdList ys++instance (Ord a, Show a) => Show (Heap a) where+ showsPrec = showsPrecUsingToList++instance (Ord a, Read a) => Read (Heap a) where+ readsPrec = readsPrecUsingFromList+++instance (Ord a, Arbitrary a) => Arbitrary (Heap a) where+ arbitrary = sized (\n -> arbTree n)+ where arbTree 0 = return E+ arbTree n =+ frequency [(1, return E),+ (4, liftM3 snode arbitrary (arbTree (n `div` 2))+ (arbTree (n `div` 4)))]++ snode x a b = sift (node x a b)++ sift E = E+ sift t@(L _ x a E)+ | a == E || x <= minElem a = t+ sift (L r x (L r' y a b) E) =+ L r y (sift (L r' x a b)) E+ sift t@(L r x a b)+ | x <= minElem a && x <= minElem b = t+ sift (L r x (L r' y a b) c)+ | y <= minElem c =+ L r y (sift (L r' x a b)) c+ sift (L r x a (L r' y b c)) =+ L r y a (sift (L r' x b c))+ sift _ = error "LeftistHeap.arbitrary: bug!"++ coarbitrary E = variant 0+ coarbitrary (L _ x a b) = + variant 1 . coarbitrary x . coarbitrary a . coarbitrary b++instance (Ord a) => Monoid (Heap a) where+ mempty = empty+ mappend = union+ mconcat = unionSeq++instance (Ord a) => Ord (Heap a) where+ compare = compareUsingToOrdList
+ src/Data/Edison/Coll/MinHeap.hs view
@@ -0,0 +1,406 @@+-- |+-- Module : Data.Edison.Coll.MinHeap+-- Copyright : Copyright (c) 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)+--+-- A generic adaptor for bags to keep the minimum element separately.++module Data.Edison.Coll.MinHeap (+ -- * Min heap adaptor type+ Min, -- instance of Coll/CollX, OrdColl/OrdCollX++ -- * CollX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,strict,structuralInvariant,++ -- * Coll operations+ toSeq, lookup, lookupM, lookupAll, lookupWithDefault, fold, fold',+ fold1, fold1', filter, partition, strictWith,++ -- * OrdCollX operations+ deleteMin,deleteMax,unsafeInsertMin,unsafeInsertMax,unsafeFromOrdSeq,+ unsafeAppend,filterLT,filterLE,filterGT,filterGE,partitionLT_GE,+ partitionLE_GT,partitionLT_GT,++ -- * OrdColl operations+ minView,minElem,maxView,maxElem,foldr,foldr',foldl,foldl',+ foldr1,foldr1',foldl1,foldl1',toOrdSeq,+ unsafeMapMonotonic,++ -- * Other supported operations+ toColl,fromColl,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,foldr,foldl,foldr1,foldl1,lookup,filter)+import Data.Edison.Prelude+import qualified Data.Edison.Coll as C+import qualified Data.Edison.Seq as S+import Data.Edison.Coll.Defaults+import Data.Edison.Seq.Defaults (tokenMatch,maybeParens)+import Data.Monoid+import Control.Monad+import Test.QuickCheck++data Min h a = E | M a h deriving (Eq)++moduleName = "Data.Edison.Coll.MinHeap"++instanceName E = "MinHeap(empty)"+instanceName (M x h) = "MinHeap(" ++ C.instanceName h ++ ")"++structuralInvariant :: (Ord a,C.OrdColl h a) => Min h a -> Bool+structuralInvariant E = True+structuralInvariant (M x h) = if C.null h then True else x <= C.minElem h++empty :: Min h a+singleton :: (C.CollX h a,Ord a) => a -> Min h a+fromSeq :: (C.OrdColl h a,Ord a,S.Sequence s) => s a -> Min h a+insert :: (C.OrdCollX h a,Ord a) => a -> Min h a -> Min h a+insertSeq :: (C.OrdColl h a,Ord a,S.Sequence s) => s a -> Min h a -> Min h a+union :: (C.OrdCollX h a,Ord a) => Min h a -> Min h a -> Min h a+unionSeq :: (C.OrdColl h a,Ord a,S.Sequence s) => s (Min h a) -> Min h a+delete :: (C.OrdColl h a,Ord a) => a -> Min h a -> Min h a+deleteAll :: (C.OrdColl h a,Ord a) => a -> Min h a -> Min h a+deleteSeq :: (C.OrdColl h a,Ord a,S.Sequence s) => s a -> Min h a -> Min h a+null :: Min h a -> Bool+size :: C.CollX h a => Min h a -> Int+member :: (C.CollX h a,Ord a) => a -> Min h a -> Bool+count :: (C.CollX h a,Ord a) => a -> Min h a -> Int+strict :: (C.CollX h a,Ord a) => Min h a -> Min h a++toSeq :: (C.Coll h a,S.Sequence s) => Min h a -> s a+lookup :: (C.Coll h a,Ord a) => a -> Min h a -> a+lookupM :: (C.Coll h a,Ord a,Monad m) => a -> Min h a -> m a+lookupAll :: (C.Coll h a,Ord a,S.Sequence s) => a -> Min h a -> s a+lookupWithDefault :: (C.Coll h a,Ord a) => a -> a -> Min h a -> a+fold :: (C.Coll h a) => (a -> b -> b) -> b -> Min h a -> b+fold1 :: (C.Coll h a) => (a -> a -> a) -> Min h a -> a+fold' :: (C.Coll h a) => (a -> b -> b) -> b -> Min h a -> b+fold1' :: (C.Coll h a) => (a -> a -> a) -> Min h a -> a+filter :: (C.OrdColl h a) => (a -> Bool) -> Min h a -> Min h a+partition :: (C.OrdColl h a) => (a -> Bool) -> Min h a -> (Min h a, Min h a)+strictWith :: (C.OrdColl h a) => (a -> b) -> Min h a -> Min h a++deleteMin :: (C.OrdColl h a,Ord a) => Min h a -> Min h a+deleteMax :: (C.OrdCollX h a,Ord a) => Min h a -> Min h a+unsafeInsertMin :: (C.OrdCollX h a,Ord a) => a -> Min h a -> Min h a+unsafeInsertMax :: (C.OrdCollX h a,Ord a) => a -> Min h a -> Min h a+unsafeFromOrdSeq :: (C.OrdCollX h a,Ord a,S.Sequence s) => s a -> Min h a+unsafeAppend :: (C.OrdCollX h a,Ord a) => Min h a -> Min h a -> Min h a+filterLT :: (C.OrdCollX h a,Ord a) => a -> Min h a -> Min h a+filterLE :: (C.OrdCollX h a,Ord a) => a -> Min h a -> Min h a+filterGT :: (C.OrdColl h a,Ord a) => a -> Min h a -> Min h a+filterGE :: (C.OrdColl h a,Ord a) => a -> Min h a -> Min h a+partitionLT_GE :: (C.OrdColl h a,Ord a) => a -> Min h a -> (Min h a, Min h a)+partitionLE_GT :: (C.OrdColl h a,Ord a) => a -> Min h a -> (Min h a, Min h a)+partitionLT_GT :: (C.OrdColl h a,Ord a) => a -> Min h a -> (Min h a, Min h a)++minView :: (C.OrdColl h a,Ord a,Monad m) => Min h a -> m (a, Min h a)+minElem :: (C.OrdColl h a,Ord a) => Min h a -> a+maxView :: (C.OrdColl h a,Ord a,Monad m) => Min h a -> m (a, Min h a)+maxElem :: (C.OrdColl h a,Ord a) => Min h a -> a+foldr :: (C.OrdColl h a,Ord a) => (a -> b -> b) -> b -> Min h a -> b+foldl :: (C.OrdColl h a,Ord a) => (b -> a -> b) -> b -> Min h a -> b+foldr1 :: (C.OrdColl h a,Ord a) => (a -> a -> a) -> Min h a -> a+foldl1 :: (C.OrdColl h a,Ord a) => (a -> a -> a) -> Min h a -> a+foldr' :: (C.OrdColl h a,Ord a) => (a -> b -> b) -> b -> Min h a -> b+foldl' :: (C.OrdColl h a,Ord a) => (b -> a -> b) -> b -> Min h a -> b+foldr1' :: (C.OrdColl h a,Ord a) => (a -> a -> a) -> Min h a -> a+foldl1' :: (C.OrdColl h a,Ord a) => (a -> a -> a) -> Min h a -> a+toOrdSeq :: (C.OrdColl h a,Ord a,S.Sequence s) => Min h a -> s a+unsafeMapMonotonic :: (C.OrdColl h a,Ord a) => + (a -> a) -> Min h a -> Min h a++fromColl :: C.OrdColl h a => h -> Min h a+fromColl = fromPrim++toColl :: C.OrdColl h a => Min h a -> h+toColl = toPrim++fromPrim xs = case C.minView xs of+ Nothing -> E+ Just (x, xs') -> M x xs'++toPrim E = C.empty+toPrim (M x xs) = C.unsafeInsertMin x xs++empty = E+singleton x = M x C.empty++fromSeq = fromPrim . C.fromSeq++insert x E = M x C.empty+insert x (M y xs)+ | x <= y = M x (C.unsafeInsertMin y xs)+ | otherwise = M y (C.insert x xs)++insertSeq xs E = fromSeq xs+insertSeq xs (M y ys) = + case C.minView xs_ys of+ Nothing -> M y C.empty+ Just (x, rest)+ | x < y -> M x (C.insert y rest)+ | otherwise -> M y xs_ys+ where xs_ys = C.insertSeq xs ys++union E ys = ys+union xs E = xs+union (M x xs) (M y ys)+ | x <= y = M x (C.union xs (C.unsafeInsertMin y ys))+ | otherwise = M y (C.union (C.unsafeInsertMin x xs) ys)++unionSeq = unionSeqUsingReduce++delete x E = E+delete x m@(M y ys)+ | x > y = M y (C.delete x ys)+ | x == y = fromPrim ys+ | otherwise = m++deleteAll x E = E+deleteAll x m@(M y ys)+ | x > y = M y (C.deleteAll x ys)+ | x == y = fromPrim (C.deleteAll x ys)+ | otherwise = m++deleteSeq = deleteSeqUsingDelete++null E = True+null (M x xs) = False++size E = 0+size (M x xs) = 1 + C.size xs+++member x E = False+member x (M y ys)+ | x > y = C.member x ys+ | otherwise = (x == y)++count x E = 0+count x (M y ys)+ | x > y = C.count x ys+ | x == y = 1 + C.count x ys+ | otherwise = 0++toSeq E = S.empty+toSeq (M x xs) = S.lcons x (C.toSeq xs)++lookup x (M y ys)+ | x > y = C.lookup x ys+ | x == y = y+lookup _ _ = error "MinHeap.lookup: empty heap"++lookupM x (M y ys)+ | x > y = C.lookupM x ys+ | x == y = return y+lookupM _ _ = fail "lookupM.lookup: XXX"++lookupAll x (M y ys)+ | x > y = C.lookupAll x ys+ | x == y = S.lcons y (C.lookupAll x ys)+lookupAll _ _ = S.empty++lookupWithDefault d x (M y ys)+ | x > y = C.lookupWithDefault d x ys+ | x == y = y+lookupWithDefault d _ _ = d++fold f e E = e+fold f e (M x xs) = f x (C.fold f e xs)++fold' f e E = e+fold' f e (M x xs) = f x $! (C.fold' f e xs)++fold1 f E = error "MinHeap.fold1: empty heap"+fold1 f (M x xs) = C.fold f x xs++fold1' f E = error "MinHeap.fold1': empty heap"+fold1' f (M x xs) = C.fold' f x xs++filter p E = E+filter p (M x xs)+ | p x = M x (C.filter p xs)+ | otherwise = fromPrim (C.filter p xs)++partition p E = (E, E)+partition p (M x xs)+ | p x = (M x ys, fromPrim zs)+ | otherwise = (fromPrim ys, M x zs)+ where (ys,zs) = C.partition p xs++deleteMin E = E+deleteMin (M x xs) = fromPrim xs++deleteMax E = E+deleteMax (M x xs)+ | C.null xs = E+ | otherwise = M x (C.deleteMax xs)++unsafeInsertMin x xs = M x (toPrim xs)++unsafeInsertMax x E = M x C.empty+unsafeInsertMax x (M y ys) = M y (C.unsafeInsertMax x ys)++unsafeFromOrdSeq xs =+ case S.lview xs of+ Nothing -> E+ Just (x,xs') -> M x (C.unsafeFromOrdSeq xs')++unsafeAppend E ys = ys+unsafeAppend (M x xs) ys = M x (C.unsafeAppend xs (toPrim ys))++filterLT x (M y ys) | y < x = M y (C.filterLT x ys)+filterLT _ _ = E++filterLE x (M y ys) | y <= x = M y (C.filterLE x ys)+filterLE _ _ = E++filterGT x (M y ys) | y <= x = fromPrim (C.filterGT x ys)+filterGT x h = h++filterGE x (M y ys) | y < x = fromPrim (C.filterGE x ys)+filterGE x h = h++partitionLT_GE x (M y ys)+ | y < x = (M y lows, fromPrim highs)+ where (lows,highs) = C.partitionLT_GE x ys+partitionLT_GE x h = (E, h)++partitionLE_GT x (M y ys) + | y <= x = (M y lows, fromPrim highs)+ where (lows,highs) = C.partitionLE_GT x ys+partitionLE_GT x h = (E, h)++partitionLT_GT x (M y ys)+ | y < x = let (lows,highs) = C.partitionLT_GT x ys+ in (M y lows, fromPrim highs)+ | y == x = (E, fromPrim (C.filterGT x ys))+partitionLT_GT x h = (E, h)+++minView E = fail "MinHeap.minView: empty heap"+minView (M x xs) = return (x, fromPrim xs)++minElem E = error "MinHeap.minElem: empty heap"+minElem (M x xs) = x++maxView E = fail "MinHeap.maxView: empty heap"+maxView (M x xs) = case C.maxView xs of+ Nothing -> return (x, E)+ Just (y,ys) -> return (y, M x ys)++maxElem E = error "MinHeap.minElem: empty heap"+maxElem (M x xs)+ | C.null xs = x+ | otherwise = C.maxElem xs++foldr f e E = e+foldr f e (M x xs) = f x (C.foldr f e xs)++foldr' f e E = e+foldr' f e (M x xs) = f x $! (C.foldr' f e xs)++foldl f e E = e+foldl f e (M x xs) = C.foldl f (f e x) xs++foldl' f e E = e+foldl' f e (M x xs) = e `seq` C.foldl' f (f e x) xs++foldr1 f E = error "MinHeap.foldr1: empty heap"+foldr1 f (M x xs)+ | C.null xs = x+ | otherwise = f x (C.foldr1 f xs)++foldr1' f E = error "MinHeap.foldr1': empty heap"+foldr1' f (M x xs)+ | C.null xs = x+ | otherwise = f x $! (C.foldr1' f xs)++foldl1 f E = error "MinHeap.foldl1: empty heap"+foldl1 f (M x xs) = C.foldl f x xs++foldl1' f E = error "MinHeap.foldl1': empty heap"+foldl1' f (M x xs) = C.foldl' f x xs++toOrdSeq E = S.empty+toOrdSeq (M x xs) = S.lcons x (C.toOrdSeq xs)++unsafeMapMonotonic = unsafeMapMonotonicUsingFoldr++strict h@E = h+strict h@(M x xs) = C.strict xs `seq` h++strictWith f h@E = h+strictWith f h@(M x xs) = f x `seq` C.strictWith f xs `seq` h+++-- instance declarations++instance (C.OrdColl h a, Ord a) => C.CollX (Min h a) a where+ {singleton = singleton; fromSeq = fromSeq; insert = insert;+ insertSeq = insertSeq; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq;+ null = null; size = size; member = member; count = count;+ strict = strict;+ structuralInvariant = structuralInvariant; instanceName c = moduleName}++instance (C.OrdColl h a, Ord a) => C.OrdCollX (Min h a) a where+ {deleteMin = deleteMin; deleteMax = deleteMax; + unsafeInsertMin = unsafeInsertMin; unsafeInsertMax = unsafeInsertMax; + unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend; + filterLT = filterLT; filterLE = filterLE; filterGT = filterGT; + filterGE = filterGE; partitionLT_GE = partitionLT_GE; + partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance (C.OrdColl h a, Ord a) => C.Coll (Min h a) a where+ {toSeq = toSeq; lookup = lookup; lookupM = lookupM; + lookupAll = lookupAll; lookupWithDefault = lookupWithDefault; + fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; strictWith = strictWith}++instance (C.OrdColl h a, Ord a) => C.OrdColl (Min h a) a where+ {minView = minView; minElem = minElem; maxView = maxView; + maxElem = maxElem; foldr = foldr; foldr' = foldr'; + foldl = foldl; foldl' = foldl'; foldr1 = foldr1; foldr1' = foldr1';+ foldl1 = foldl1; foldl1' = foldl1'; toOrdSeq = toOrdSeq;+ unsafeMapMonotonic = unsafeMapMonotonic}++-- instance Eq is derived++instance (C.OrdColl h a, Show h) => Show (Min h a) where+ showsPrec i xs rest+ | i == 0 = concat [ moduleName,".fromColl ",showsPrec 10 (toColl xs) rest]+ | otherwise = concat ["(",moduleName,".fromColl ",showsPrec 10 (toColl xs) (')':rest)]++instance (C.OrdColl h a, Read h) => Read (Min h a) where+ readsPrec i xs = maybeParens p xs+ where p xs = tokenMatch (moduleName++".fromColl") xs+ >>= readsPrec 10+ >>= \(coll,rest) -> return (fromColl coll,rest)++instance (C.OrdColl h a,Arbitrary h,Arbitrary a) => Arbitrary (Min h a) where+ arbitrary = do xs <- arbitrary+ x <- arbitrary+ i <- arbitrary :: Gen Int+ return (if C.null xs || x <= C.minElem xs then M x xs+ else if odd i then M (C.minElem xs) xs+ else fromPrim xs)++ coarbitrary E = variant 0+ coarbitrary (M x xs) = variant 1 . coarbitrary x . coarbitrary xs++instance (C.OrdColl h a) => Monoid (Min h a) where+ mempty = empty+ mappend = union+ mconcat = unionSeq++instance (Eq h, C.OrdColl h a) => Ord (Min h a) where+ compare = compareUsingToOrdList
+ src/Data/Edison/Coll/SkewHeap.hs view
@@ -0,0 +1,457 @@+-- |+-- Module : Data.Edison.Coll.SkewHeap+-- 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)+--+-- Skew heaps.+--+-- /References:/+--+-- * Daniel Sleator and Robert Tarjan. \"Self-Adjusting Heaps\".+-- /SIAM Journal on Computing/, 15(1):52-69, February 1986.++module Data.Edison.Coll.SkewHeap (+ -- * Type of skew heaps+ Heap, -- instance of Coll/CollX, OrdColl/OrdCollX++ -- * CollX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,strict,structuralInvariant,++ -- * Coll operations+ toSeq, lookup, lookupM, lookupAll, lookupWithDefault, fold, fold',+ fold1, fold1', filter, partition, strictWith,++ -- * OrdCollX operations+ deleteMin,deleteMax,unsafeInsertMin,unsafeInsertMax,unsafeFromOrdSeq,+ unsafeAppend,filterLT,filterLE,filterGT,filterGE,partitionLT_GE,+ partitionLE_GT,partitionLT_GT,++ -- * OrdColl operations+ minView,minElem,maxView,maxElem,foldr,foldr',foldl,foldl',+ foldr1,foldr1',foldl1,foldl1',toOrdSeq,+ unsafeMapMonotonic,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,foldr,foldl,foldr1,foldl1,lookup,filter)+import Data.Edison.Prelude+import qualified Data.Edison.Coll as C+import qualified Data.Edison.Seq as S+import Data.Edison.Coll.Defaults+import Data.Monoid+import Control.Monad+import Test.QuickCheck++moduleName = "Data.Edison.Coll.SkewHeap"++data Heap a = E | T a (Heap a) (Heap a)++-- invariants:+-- * Heap order+structuralInvariant :: Ord a => Heap a -> Bool+structuralInvariant E = True+structuralInvariant t@(T x l r) = isMin x t+ where isMin x E = True+ isMin x (T y l r) = x <= y && isMin y l && isMin y r+++{-+For delete,deleteAll,filter,partition: could compute fringe and reduce+rather that rebuilding with union at every deleted node+-}++empty :: Ord a => Heap a+empty = E++singleton :: Ord a => a -> Heap a+singleton x = T x E E++insert :: Ord a => a -> Heap a -> Heap a+insert x E = T x E E+insert x h@(T y a b)+ | x <= y = T x h E+ | otherwise = T y (insert x b) a++union :: Ord a => Heap a -> Heap a -> Heap a+union E h = h+union h@(T x a b) h' = union' h x a b h'+ where union' h x a b E = h+ union' hx x a b hy@(T y c d)+ | x <= y = T x (union' hy y c d b) a+ | otherwise = T y (union' hx x a b d) c++delete :: Ord a => a -> Heap a -> Heap a+delete x h = case del h of+ Just h' -> h'+ Nothing -> h+ where del (T y a b) =+ case compare x y of+ LT -> Nothing+ EQ -> Just (union a b)+ GT -> case del b of+ Just b' -> Just (T y a b')+ Nothing -> case del a of+ Just a' -> Just (T y a' b)+ Nothing -> Nothing+ del E = Nothing++deleteAll :: Ord a => a -> Heap a -> Heap a+deleteAll x h@(T y a b) =+ case compare x y of+ LT -> h+ EQ -> union (deleteAll x a) (deleteAll x b)+ GT -> T y (deleteAll x a) (deleteAll x b)+deleteAll x E = E++null :: Ord a => Heap a -> Bool+null E = True+null _ = False++size :: Ord a => Heap a -> Int+size h = sz h 0+ where sz E i = i+ sz (T _ a b) i = sz a (sz b (i + 1))++member :: Ord a => a -> Heap a -> Bool+member x E = False+member x (T y a b) =+ case compare x y of+ LT -> False+ EQ -> True+ GT -> member x b || member x a++count :: Ord a => a -> Heap a -> Int+count x E = 0+count x (T y a b) =+ case compare x y of+ LT -> 0+ EQ -> 1 + count x b + count x a+ GT -> count x b + count x a++toSeq :: (Ord a,S.Sequence seq) => Heap a -> seq a+toSeq h = tol h S.empty+ where tol E rest = rest+ tol (T x a b) rest = S.lcons x (tol b (tol a rest))++lookupM :: (Ord a, Monad m) => a -> Heap a -> m a+lookupM x E = fail "SkewHeap.lookupM: XXX"+lookupM x (T y a b) =+ case compare x y of+ LT -> fail "SkewHeap.lookupM: XXX"+ EQ -> return y+ GT -> case lookupM x b `mplus` lookupM x a of+ Nothing -> fail "SkewHeap.lookupM: XXX"+ Just x -> return x++lookupAll :: (Ord a,S.Sequence seq) => a -> Heap a -> seq a+lookupAll x h = look h S.empty+ where look E ys = ys+ look (T y a b) ys =+ case compare x y of+ LT -> ys+ EQ -> S.lcons y (look b (look a ys))+ GT -> look b (look a ys)++fold :: Ord a => (a -> b -> b) -> b -> Heap a -> b+fold f e E = e+fold f e (T x a b) = f x (fold f (fold f e a) b)++fold' :: Ord a => (a -> b -> b) -> b -> Heap a -> b+fold' f e E = e+fold' f e (T x a b) = e `seq` f x $! (fold' f (fold' f e a) b)++fold1 :: Ord a => (a -> a -> a) -> Heap a -> a+fold1 f E = error "SkewHeap.fold1: empty collection"+fold1 f (T x a b) = fold f (fold f x a) b++fold1' :: Ord a => (a -> a -> a) -> Heap a -> a+fold1' f E = error "SkewHeap.fold1': empty collection"+fold1' f (T x a b) = fold' f (fold' f x a) b++filter :: Ord a => (a -> Bool) -> Heap a -> Heap a+filter p E = E+filter p (T x a b)+ | p x = T x (filter p a) (filter p b)+ | otherwise = union (filter p a) (filter p b)++partition :: Ord a => (a -> Bool) -> Heap a -> (Heap a, Heap a)+partition p E = (E, E)+partition p (T x a b)+ | p x = (T x a' b', union a'' b'')+ | otherwise = (union a' b', T x a'' b'')+ where (a', a'') = partition p a+ (b', b'') = partition p b+++deleteMin :: Ord a => Heap a -> Heap a+deleteMin E = E+deleteMin (T x a b) = union a b++deleteMax :: Ord a => Heap a -> Heap a+deleteMax h = case maxView h of+ Nothing -> E+ Just (x,h') -> h'++unsafeInsertMin :: Ord a => a -> Heap a -> Heap a+unsafeInsertMin x h = T x h E++unsafeAppend :: Ord a => Heap a -> Heap a -> Heap a+unsafeAppend E h = h+unsafeAppend (T x a b) h = T x (unsafeAppend b h) a++filterLT :: Ord a => a -> Heap a -> Heap a+filterLT y (T x a b) | x < y = T x (filterLT y a) (filterLT y b)+filterLT y _ = E++filterLE :: Ord a => a -> Heap a -> Heap a+filterLE y (T x a b) | x <= y = T x (filterLE y a) (filterLE y b)+filterLE y _ = E++filterGT :: Ord a => a -> Heap a -> Heap a+filterGT y h = C.unionList (collect h [])+ where collect E hs = hs+ collect h@(T x a b) hs+ | x > y = h : hs+ | otherwise = collect a (collect b hs)++filterGE :: Ord a => a -> Heap a -> Heap a+filterGE y h = C.unionList (collect h [])+ where collect E hs = hs+ collect h@(T x a b) hs+ | x >= y = h : hs+ | otherwise = collect b (collect a hs)++partitionLT_GE :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLT_GE y h = (h', C.unionList hs)+ where (h', hs) = collect h []++ collect E hs = (E, hs)+ collect h@(T x a b) hs+ | x >= y = (E, h:hs)+ | otherwise = let (a', hs') = collect a hs+ (b', hs'') = collect b hs'+ in (T x a' b', hs'')++partitionLE_GT :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLE_GT y h = (h', C.unionList hs)+ where (h', hs) = collect h []++ collect E hs = (E, hs)+ collect h@(T x a b) hs+ | x > y = (E, h:hs)+ | otherwise = let (a', hs') = collect a hs+ (b', hs'') = collect b hs'+ in (T x a' b', hs'')++partitionLT_GT :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLT_GT y h = (h', C.unionList hs)+ where (h', hs) = collect h []++ collect E hs = (E, hs)+ collect h@(T x a b) hs = + case compare x y of+ GT -> (E, h:hs)+ EQ -> let (a', hs') = collect a hs+ (b', hs'') = collect b hs'+ in (union a' b', hs'')+ LT -> let (a', hs') = collect a hs+ (b', hs'') = collect b hs'+ in (T x a' b', hs'')++minView :: (Ord a, Monad m) => Heap a -> m (a, Heap a)+minView E = fail "SkewHeap.minView: empty heap"+minView (T x a b) = return (x, union a b)++minElem :: Ord a => Heap a -> a+minElem E = error "SkewHeap.minElem: empty collection"+minElem (T x a b) = x++maxView :: (Ord a, Monad m) => Heap a -> m (a, Heap a)+maxView E = fail "SkewHeap.maxView: empty heap"+maxView (T x E E) = return (x, E)+maxView (T x a E) = return (y, T x a' E)+ where Just (y, a') = maxView a+maxView (T x E a) = return (y, T x a' E)+ where Just (y, a') = maxView a+maxView (T x a b)+ | y >= z = return (y, T x a' b)+ | otherwise = return (z, T x a b')+ where Just (y, a') = maxView a+ Just (z, b') = maxView b++-- warning: maxView and maxElem may disagree if root is equal to max!++maxElem :: Ord a => Heap a -> a+maxElem E = error "SkewHeap.maxElem: empty collection"+maxElem (T x E E) = x+maxElem (T x a E) = maxElem a+maxElem (T x E a) = maxElem a+maxElem (T x a b) = findMax b (findLeaf a)+ where findMax E m = m+ findMax (T x E E) m+ | m >= x = m+ | otherwise = x+ findMax (T x a E) m = findMax a m+ findMax (T x E a) m = findMax a m+ findMax (T x a b) m = findMax a (findMax b m)++ findLeaf E = error "SkewHeap.maxElem: bug"+ findLeaf (T x E E) = x+ findLeaf (T x a E) = findLeaf a+ findLeaf (T x E a) = findLeaf a+ findLeaf (T x a b) = findMax b (findLeaf a)++foldr :: Ord a => (a -> b -> b) -> b -> Heap a -> b+foldr f e E = e+foldr f e (T x a b) = f x (foldr f e (union a b))++foldr' :: Ord a => (a -> b -> b) -> b -> Heap a -> b+foldr' f e E = e+foldr' f e (T x a b) = e `seq` f x $! (foldr' f e (union a b))++foldl :: Ord a => (b -> a -> b) -> b -> Heap a -> b+foldl f e E = e+foldl f e (T x a b) = foldl f (f e x) (union a b)++foldl' :: Ord a => (b -> a -> b) -> b -> Heap a -> b+foldl' f e E = e+foldl' f e (T x a b) = e `seq` foldl' f (f e x) (union a b)++foldr1 :: Ord a => (a -> a -> a) -> Heap a -> a+foldr1 f E = error "SkewHeap.foldr1: empty collection"+foldr1 f (T x E E) = x+foldr1 f (T x a b) = f x (foldr1 f (union a b))++foldr1' :: Ord a => (a -> a -> a) -> Heap a -> a+foldr1' f E = error "SkewHeap.foldr1': empty collection"+foldr1' f (T x E E) = x+foldr1' f (T x a b) = f x $! (foldr1' f (union a b))++foldl1 :: Ord a => (a -> a -> a) -> Heap a -> a+foldl1 f E = error "SkewHeap.foldl1: empty collection"+foldl1 f (T x a b) = foldl f x (union a b)++foldl1' :: Ord a => (a -> a -> a) -> Heap a -> a+foldl1' f E = error "SkewHeap.foldl1': empty collection"+foldl1' f (T x a b) = foldl' f x (union a b)++{- ???? -}+unsafeMapMonotonic :: Ord a => (a -> a) -> Heap a -> Heap a+unsafeMapMonotonic f E = E+unsafeMapMonotonic f (T x a b) =+ T (f x) (unsafeMapMonotonic f a) (unsafeMapMonotonic f b)+++strict :: Heap a -> Heap a+strict h@E = h+strict h@(T x l r) = strict l `seq` strict r `seq` h++strictWith :: (a -> b) -> Heap a -> Heap a+strictWith f h@E = h+strictWith f h@(T x l r) = f x `seq` strictWith f l `seq` strictWith f r `seq` h++-- the remaining functions all use default definitions++fromSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a+fromSeq = fromSeqUsingUnionSeq++insertSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a -> Heap a+insertSeq = insertSeqUsingUnion++unionSeq :: (Ord a,S.Sequence seq) => seq (Heap a) -> Heap a+unionSeq = unionSeqUsingReduce++deleteSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a -> Heap a+deleteSeq = deleteSeqUsingDelete++lookup :: Ord a => a -> Heap a -> a+lookup = lookupUsingLookupM++lookupWithDefault :: Ord a => a -> a -> Heap a -> a+lookupWithDefault = lookupWithDefaultUsingLookupM++unsafeInsertMax :: Ord a => a -> Heap a -> Heap a+unsafeInsertMax = unsafeInsertMaxUsingUnsafeAppend++unsafeFromOrdSeq :: (Ord a,S.Sequence seq) => seq a -> Heap a+unsafeFromOrdSeq = unsafeFromOrdSeqUsingUnsafeInsertMin++toOrdSeq :: (Ord a,S.Sequence seq) => Heap a -> seq a+toOrdSeq = toOrdSeqUsingFoldr++-- instance declarations++instance Ord a => C.CollX (Heap a) a where+ {singleton = singleton; fromSeq = fromSeq; insert = insert;+ insertSeq = insertSeq; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq;+ null = null; size = size; member = member; count = count;+ strict = strict;+ structuralInvariant = structuralInvariant; instanceName c = moduleName}++instance Ord a => C.OrdCollX (Heap a) a where+ {deleteMin = deleteMin; deleteMax = deleteMax; + unsafeInsertMin = unsafeInsertMin; unsafeInsertMax = unsafeInsertMax; + unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend; + filterLT = filterLT; filterLE = filterLE; filterGT = filterGT; + filterGE = filterGE; partitionLT_GE = partitionLT_GE; + partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance Ord a => C.Coll (Heap a) a where+ {toSeq = toSeq; lookup = lookup; lookupM = lookupM; + lookupAll = lookupAll; lookupWithDefault = lookupWithDefault; + fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; strictWith = strictWith}++instance Ord a => C.OrdColl (Heap a) a where+ {minView = minView; minElem = minElem; maxView = maxView; + maxElem = maxElem; foldr = foldr; foldr' = foldr';+ foldl = foldl; foldl' = foldl'; foldr1 = foldr1; foldr1' = foldr1';+ foldl1 = foldl1; foldl1' = fold1'; toOrdSeq = toOrdSeq;+ unsafeMapMonotonic = unsafeMapMonotonic}++instance Ord a => Eq (Heap a) where+ xs == ys = C.toOrdList xs == C.toOrdList ys++instance (Ord a, Show a) => Show (Heap a) where+ showsPrec = showsPrecUsingToList++instance (Ord a, Read a) => Read (Heap a) where+ readsPrec = readsPrecUsingFromList+++instance (Ord a, Arbitrary a) => Arbitrary (Heap a) where+ arbitrary = sized (\n -> arbTree n)+ where arbTree 0 = return E+ arbTree n =+ frequency [(1, return E),+ (4, liftM3 sift arbitrary (arbTree (n `div` 2))+ (arbTree (n `div` 4)))]++ sift x s@(T y a b) E+ | y < x = T y (sift x a b) E+ sift x E s@(T y a b)+ | y < x = T y E (sift x a b)+ sift x s@(T y a b) t@(T z c d)+ | y < x && y <= z = T y (sift x a b) t+ | z < x = T z s (sift x c d)+ sift x a b = T x a b++ coarbitrary E = variant 0+ coarbitrary (T x a b) = + variant 1 . coarbitrary x . coarbitrary a . coarbitrary b++instance (Ord a) => Monoid (Heap a) where+ mempty = empty+ mappend = union+ mconcat = unionSeq++instance (Ord a) => Ord (Heap a) where+ compare = compareUsingToOrdList
+ src/Data/Edison/Coll/SplayHeap.hs view
@@ -0,0 +1,493 @@+-- |+-- Module : Data.Edison.Coll.SplayHeap+-- Copyright : Copyright (c) 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)+--+-- Splay heaps.+--+-- If 'minElem' is called frequently, then SplayHeap should+-- be used in conjunction with "Data.Edison.Coll.MinHeap".+--+-- /References:/+--+-- * Chris Okasaki. /Purely Functional Data Structures/. 1998.+-- Section 5.4.++module Data.Edison.Coll.SplayHeap (+ -- * Type of splay heaps+ Heap, -- instance of Coll/CollX, OrdColl/OrdCollX++ -- * CollX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,strict,structuralInvariant,++ -- * Coll operations+ toSeq, lookup, lookupM, lookupAll, lookupWithDefault, fold, fold',+ fold1, fold1', filter, partition, strictWith,++ -- * OrdCollX operations+ deleteMin,deleteMax,unsafeInsertMin,unsafeInsertMax,unsafeFromOrdSeq,+ unsafeAppend,filterLT,filterLE,filterGT,filterGE,partitionLT_GE,+ partitionLE_GT,partitionLT_GT,++ -- * OrdColl operations+ minView,minElem,maxView,maxElem,foldr,foldr',foldl,foldl',+ foldr1,foldr1',foldl1,foldl1',toOrdSeq,+ unsafeMapMonotonic,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,foldr,foldl,foldr1,foldl1,lookup,filter)+import Data.Edison.Prelude+import qualified Data.Edison.Coll as C+import qualified Data.Edison.Seq as S+import Data.Edison.Coll.Defaults+import Data.Monoid+import Control.Monad+import Test.QuickCheck++moduleName = "Data.Edison.Coll.SplayHeap"++data Heap a = E | T (Heap a) a (Heap a)++-- invariants:+-- * Binary Search Tree order (allowing duplicates)++structuralInvariant :: Ord a => Heap a -> Bool+structuralInvariant t = bounded Nothing Nothing t+ where bounded _ _ E = True+ bounded lo hi (T l x r) = cmp_l lo x + && cmp_r x hi+ && bounded lo (Just x) l+ && bounded (Just x) hi r++ cmp_l Nothing _ = True+ cmp_l (Just x) y = x <= y++ cmp_r _ Nothing = True+ cmp_r x (Just y) = x <= y+++empty :: Heap a+singleton :: a -> Heap a+fromSeq :: (Ord a,S.Sequence s) => s a -> Heap a+insert :: Ord a => a -> Heap a -> Heap a+insertSeq :: (Ord a,S.Sequence s) => s a -> Heap a -> Heap a+union :: Ord a => Heap a -> Heap a -> Heap a+unionSeq :: (Ord a,S.Sequence s) => s (Heap a) -> Heap a+delete :: Ord a => a -> Heap a -> Heap a+deleteAll :: Ord a => a -> Heap a -> Heap a+deleteSeq :: (Ord a,S.Sequence s) => s a -> Heap a -> Heap a+null :: Heap a -> Bool+size :: Heap a -> Int+member :: Ord a => a -> Heap a -> Bool+count :: Ord a => a -> Heap a -> Int+strict :: Heap a -> Heap a++toSeq :: (Ord a, S.Sequence s) => Heap a -> s a+lookup :: Ord a => a -> Heap a -> a+lookupM :: (Ord a,Monad m) => a -> Heap a -> m a+lookupAll :: (Ord a,S.Sequence s) => a -> Heap a -> s a+lookupWithDefault :: Ord a => a -> a -> Heap a -> a+fold :: Ord a => (a -> b -> b) -> b -> Heap a -> b+fold1 :: Ord a => (a -> a -> a) -> Heap a -> a+fold' :: Ord a => (a -> b -> b) -> b -> Heap a -> b+fold1' :: Ord a => (a -> a -> a) -> Heap a -> a+filter :: Ord a => (a -> Bool) -> Heap a -> Heap a+partition :: Ord a => (a -> Bool) -> Heap a -> (Heap a, Heap a)+strictWith :: (a -> b) -> Heap a -> Heap a++deleteMin :: Ord a => Heap a -> Heap a+deleteMax :: Ord a => Heap a -> Heap a+unsafeInsertMin :: Ord a => a -> Heap a -> Heap a+unsafeInsertMax :: Ord a => a -> Heap a -> Heap a+unsafeFromOrdSeq :: (Ord a,S.Sequence s) => s a -> Heap a+unsafeAppend :: Ord a => Heap a -> Heap a -> Heap a+filterLT :: Ord a => a -> Heap a -> Heap a+filterLE :: Ord a => a -> Heap a -> Heap a+filterGT :: Ord a => a -> Heap a -> Heap a+filterGE :: Ord a => a -> Heap a -> Heap a+partitionLT_GE :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLE_GT :: Ord a => a -> Heap a -> (Heap a, Heap a)+partitionLT_GT :: Ord a => a -> Heap a -> (Heap a, Heap a)++minView :: (Ord a,Monad m) => Heap a -> m (a, Heap a)+minElem :: Ord a => Heap a -> a+maxView :: (Ord a,Monad m) => Heap a -> m (a, Heap a)+maxElem :: Ord a => Heap a -> a+foldr :: Ord a => (a -> b -> b) -> b -> Heap a -> b+foldl :: Ord a => (b -> a -> b) -> b -> Heap a -> b+foldr1 :: Ord a => (a -> a -> a) -> Heap a -> a+foldl1 :: Ord a => (a -> a -> a) -> Heap a -> a+foldr' :: Ord a => (a -> b -> b) -> b -> Heap a -> b+foldl' :: Ord a => (b -> a -> b) -> b -> Heap a -> b+foldr1' :: Ord a => (a -> a -> a) -> Heap a -> a+foldl1' :: Ord a => (a -> a -> a) -> Heap a -> a+toOrdSeq :: (Ord a,S.Sequence s) => Heap a -> s a++unsafeMapMonotonic :: (a -> b) -> Heap a -> Heap b++empty = E+singleton x = T E x E++insert x xs = T a x b+ where (a,b) = partitionLE_GT x xs++union E ys = ys+union (T a x b) ys = T (union c a) x (union d b)+ where (c,d) = partitionLE_GT x ys++delete x xs =+ let (a,b) = partitionLE_GT x xs+ in case maxView a of+ Nothing -> b+ Just (y, a')+ | x > y -> T a' y b+ | otherwise -> unsafeAppend a' b++deleteAll x xs = unsafeAppend a b+ where (a,b) = partitionLT_GT x xs++null E = True+null (T a x b) = False++size = sz 0+ where sz n E = n+ sz n (T a x b) = sz (sz (1+n) a) b+ +member x E = False+member x (T a y b) = if x < y then member x a else x==y || member x b++count = cnt 0+ where cnt n x E = n+ cnt n x (T a y b)+ | x < y = cnt n x a+ | x > y = cnt n x b+ | otherwise = cnt (cnt (1+n) x a) x b++toSeq xs = tos xs S.empty+ where tos E rest = rest+ tos (T a x b) rest = S.lcons x (tos a (tos b rest))++lookup x E = error "SplayHeap.lookup: empty heap"+lookup x (T a y b)+ | x < y = lookup x a+ | x > y = lookup x b+ | otherwise = y++lookupM x E = fail "SplayHeap.lookup: empty heap"+lookupM x (T a y b)+ | x < y = lookupM x a+ | x > y = lookupM x b+ | otherwise = return y++lookupWithDefault d x E = d+lookupWithDefault d x (T a y b)+ | x < y = lookupWithDefault d x a+ | x > y = lookupWithDefault d x b+ | otherwise = y++lookupAll x xs = look xs x S.empty+ where look E x rest = rest+ look (T a y b) x rest+ | x < y = look a x rest+ | x > y = look b x rest+ | otherwise = look a x (S.lcons y (look b x rest))++fold f e E = e+fold f e (T a x b) = f x (fold f (fold f e b) a)++fold' f e E = e+fold' f e (T a x b) = e `seq` f x $! (fold' f (fold' f e b) a)++fold1 f E = error "SplayHeap.fold1: empty heap"+fold1 f (T a x b) = fold f (fold f x b) a++fold1' f E = error "SplayHeap.fold1': empty heap"+fold1' f (T a x b) = fold' f (fold' f x b) a++filter p E = E+filter p (T a x b) + | p x = T (filter p a) x (filter p b)+ | otherwise = unsafeAppend (filter p a) (filter p b)++partition p E = (E, E)+partition p (T a x b)+ | p x = (T a0 x b0, unsafeAppend a1 b1)+ | otherwise = (unsafeAppend a0 b0, T a1 x b1)+ where (a0,a1) = partition p a+ (b0,b1) = partition p b++deleteMin E = E+deleteMin (T a x b) = del a x b+ where del E x b = b+ del (T E x b) y c = T b y c+ del (T (T a x b) y c) z d = T (del a x b) y (T c z d)++deleteMax E = E+deleteMax (T a x b) = del a x b+ where del a x E = a+ del a x (T b y E) = T a x b+ del a x (T b y (T c z d)) = T (T a x b) y (del c z d)++unsafeInsertMin x xs = T E x xs+unsafeInsertMax x xs = T xs x E++unsafeAppend a b = case maxView a of+ Nothing -> b+ Just (x, a') -> T a' x b++filterLT k E = E+filterLT k t@(T a x b) = + if x >= k then filterLT k a+ else case b of+ E -> t+ T ba y bb ->+ if y >= k then T a x (filterLT k ba) + else T (T a x ba) y (filterLT k bb)++filterLE k E = E+filterLE k t@(T a x b) = + if x > k then filterLE k a+ else case b of+ E -> t+ T ba y bb ->+ if y > k then T a x (filterLE k ba) + else T (T a x ba) y (filterLE k bb)++filterGT k E = E+filterGT k t@(T a x b) =+ if x <= k then filterGT k b+ else case a of+ E -> t+ T aa y ab ->+ if y <= k then T (filterGT k ab) x b+ else T (filterGT k aa) y (T ab x b)++filterGE k E = E+filterGE k t@(T a x b) =+ if x < k then filterGE k b+ else case a of+ E -> t+ T aa y ab ->+ if y < k then T (filterGE k ab) x b+ else T (filterGE k aa) y (T ab x b)++partitionLT_GE k E = (E,E)+partitionLT_GE k t@(T a x b) =+ if x >= k then+ case a of+ E -> (E,t)+ T aa y ab ->+ if y >= k then+ let (small,big) = partitionLT_GE k aa+ in (small, T big y (T ab x b))+ else+ let (small,big) = partitionLT_GE k ab+ in (T aa y small, T big x b)+ else+ case b of+ E -> (t,E)+ T ba y bb ->+ if y >= k then+ let (small,big) = partitionLT_GE k ba+ in (T a x small, T big y bb)+ else+ let (small,big) = partitionLT_GE k bb+ in (T (T a x ba) y small, big)++partitionLE_GT k E = (E,E)+partitionLE_GT k t@(T a x b) =+ if x > k then+ case a of+ E -> (E,t)+ T aa y ab ->+ if y > k then+ let (small,big) = partitionLE_GT k aa+ in (small, T big y (T ab x b))+ else+ let (small,big) = partitionLE_GT k ab+ in (T aa y small, T big x b)+ else+ case b of+ E -> (t,E)+ T ba y bb ->+ if y > k then+ let (small,big) = partitionLE_GT k ba+ in (T a x small, T big y bb)+ else+ let (small,big) = partitionLE_GT k bb+ in (T (T a x ba) y small, big)+++-- could specialize calls to filterLT/filterGT+partitionLT_GT k E = (E,E)+partitionLT_GT k t@(T a x b) =+ if x > k then+ case a of+ E -> (E,t)+ T aa y ab ->+ if y > k then+ let (small,big) = partitionLT_GT k aa+ in (small, T big y (T ab x b))+ else if y < k then+ let (small,big) = partitionLT_GT k ab+ in (T aa y small, T big x b)+ else (filterLT k aa, T (filterGT k ab) x b)+ else if x < k then+ case b of+ E -> (t,E)+ T ba y bb ->+ if y > k then+ let (small,big) = partitionLT_GT k ba+ in (T a x small, T big y bb)+ else if y < k then+ let (small,big) = partitionLT_GT k bb+ in (T (T a x ba) y small, big)+ else (T a x (filterLT k ba), filterGT k bb)+ else (filterLT k a, filterGT k b)++minView E = fail "SplayHeap.minView: empty heap"+minView (T a x b) = return (y, ys)+ where (y,ys) = minv a x b+ minv E x b = (x,b)+ minv (T E x b) y c = (x,T b y c)+ minv (T (T a x b) y c) z d = (w,T ab y (T c z d))+ where (w,ab) = minv a x b++minElem E = error "SplayHeap.minElem: empty heap"+minElem (T a x b) = minel a x+ where minel E x = x+ minel (T a x b) _ = minel a x+++maxView E = fail "SplayHeap.maxView: empty heap"+maxView (T a x b) = return (y,ys)+ where (ys,y) = maxv a x b+ maxv a x E = (a,x)+ maxv a x (T b y E) = (T a x b,y)+ maxv a x (T b y (T c z d)) = (T (T a x b) y cd,w)+ where (cd,w) = maxv c z d++maxElem E = error "SplayHeap.minElem: empty heap"+maxElem (T a x b) = maxel x b+ where maxel x E = x+ maxel _ (T a x b) = maxel x b++foldr f e E = e+foldr f e (T a x b) = foldr f (f x (foldr f e b)) a++foldr' f e E = e+foldr' f e (T a x b) = foldr' f (f x $! (foldr' f e b)) a++foldl f e E = e+foldl f e (T a x b) = foldl f (f (foldl f e a) x) b++foldl' f e E = e+foldl' f e (T a x b) = e `seq` foldl' f ((f $! (foldl' f e a)) x) b++foldr1 f E = error "SplayHeap.foldr1: empty heap"+foldr1 f (T a x b) = foldr f (myfold f x b) a+ where myfold f x E = x+ myfold f x (T a y b) = f x (foldr f (myfold f y b) a)++foldr1' f E = error "SplayHeap.foldr1': empty heap"+foldr1' f (T a x b) = foldr' f (myfold f x b) a+ where myfold f x E = x+ myfold f x (T a y b) = f x $! (foldr' f (myfold f y b) a)++foldl1 f E = error "SplayHeap.foldl1: empty heap"+foldl1 f (T a x b) = foldl f (myfold f a x) b+ where myfold f E x = x+ myfold f (T a x b) y = f (foldl f (myfold f a x) b) y++foldl1' f E = error "SplayHeap.foldl1': empty heap"+foldl1' f (T a x b) = foldl' f (myfold f a x) b+ where myfold f E x = x+ myfold f (T a x b) y = (f $! (foldl f (myfold f a x) b)) y++toOrdSeq xs = tos xs S.empty+ where tos E rest = rest+ tos (T a x b) rest = tos a (S.lcons x (tos b rest))++unsafeMapMonotonic f E = E+unsafeMapMonotonic f (T a x b) =+ T (unsafeMapMonotonic f a) (f x) (unsafeMapMonotonic f b)++strict h@E = h+strict h@(T l x r) = strict l `seq` strict r `seq` h++strictWith f h@E = h+strictWith f h@(T l x r) = f x `seq` strictWith f l `seq` strictWith f r `seq` h++-- the remaining functions all use defaults++fromSeq = fromSeqUsingFoldr+insertSeq = insertSeqUsingFoldr+unionSeq = unionSeqUsingReduce+deleteSeq = deleteSeqUsingDelete+unsafeFromOrdSeq = unsafeFromOrdSeqUsingUnsafeInsertMin++-- instance declarations++instance Ord a => C.CollX (Heap a) a where+ {singleton = singleton; fromSeq = fromSeq; insert = insert;+ insertSeq = insertSeq; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq;+ null = null; size = size; member = member; count = count;+ strict = strict;+ structuralInvariant = structuralInvariant; instanceName c = moduleName}++instance Ord a => C.OrdCollX (Heap a) a where+ {deleteMin = deleteMin; deleteMax = deleteMax; + unsafeInsertMin = unsafeInsertMin; unsafeInsertMax = unsafeInsertMax; + unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend; + filterLT = filterLT; filterLE = filterLE; filterGT = filterGT; + filterGE = filterGE; partitionLT_GE = partitionLT_GE; + partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance Ord a => C.Coll (Heap a) a where+ {toSeq = toSeq; lookup = lookup; lookupM = lookupM; + lookupAll = lookupAll; lookupWithDefault = lookupWithDefault; + fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ strictWith = strictWith;+ filter = filter; partition = partition}++instance Ord a => C.OrdColl (Heap a) a where+ {minView = minView; minElem = minElem; maxView = maxView; + maxElem = maxElem; foldr = foldr; foldr' = foldr'; foldl = foldl; + foldl' = foldl'; foldr1 = foldr1; foldr1' = foldr1';+ foldl1 = foldl1; foldl1' = foldl1'; toOrdSeq = toOrdSeq;+ unsafeMapMonotonic = unsafeMapMonotonic}+++instance Ord a => Eq (Heap a) where+ xs == ys = C.toOrdList xs == C.toOrdList ys++instance (Ord a, Show a) => Show (Heap a) where+ showsPrec = showsPrecUsingToList++instance (Ord a, Read a) => Read (Heap a) where+ readsPrec = readsPrecUsingFromList++instance (Ord a,Arbitrary a) => Arbitrary (Heap a) where+ arbitrary = do xs <- arbitrary+ return (C.fromList xs)++ coarbitrary E = variant 0+ coarbitrary (T a x b) = + variant 1 . coarbitrary a . coarbitrary x . coarbitrary b++instance (Ord a) => Monoid (Heap a) where+ mempty = empty+ mappend = union+ mconcat = unionSeq++instance (Ord a) => Ord (Heap a) where+ compare = compareUsingToOrdList
+ src/Data/Edison/Coll/StandardSet.hs view
@@ -0,0 +1,272 @@+-- |+-- Module : Data.Edison.Coll+-- 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)+--+-- The standard library "Data.Set" repackaged as an Edison collection.++module Data.Edison.Coll.StandardSet (+ -- * Set type+ Set,++ -- * CollX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,strict,++ -- * Coll operations+ toSeq,lookup,lookupM,lookupAll,lookupWithDefault,fold,fold',+ fold1,fold1',filter,partition,strictWith,structuralInvariant,++ -- * OrdCollX operations+ deleteMin,deleteMax,unsafeInsertMin,unsafeInsertMax,unsafeFromOrdSeq,+ unsafeAppend,filterLT,filterLE,filterGT,filterGE,partitionLT_GE,+ partitionLE_GT,partitionLT_GT,++ -- * OrdColl operations+ minView,minElem,maxView,maxElem,foldr,foldr',foldl,foldl',+ foldr1,foldr1',foldl1,foldl1',toOrdSeq,unsafeMapMonotonic,++ -- * SetX operations+ intersection,difference,symmetricDifference,properSubset,subset,++ -- * Set operations+ fromSeqWith,insertWith,insertSeqWith,unionl,unionr,unionWith,+ unionSeqWith,intersectionWith,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,foldr,foldl,foldr1,foldl1,lookup,filter)+import qualified Prelude+import qualified Data.List++import Data.Edison.Prelude+import qualified Data.Edison.Coll as C+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Seq.ListSeq as L+import Data.Edison.Coll.Defaults+import Test.QuickCheck++import qualified Data.Set as DS++-- signatures for exported functions+moduleName :: String+empty :: Set a+singleton :: a -> Set a+fromSeq :: (Ord a,S.Sequence seq) => seq a -> Set a+insert :: Ord a => a -> Set a -> Set a+insertSeq :: (Ord a,S.Sequence seq) => seq a -> Set a -> Set a+union :: Ord a => Set a -> Set a -> Set a+unionSeq :: (Ord a,S.Sequence seq) => seq (Set a) -> Set a+delete :: Ord a => a -> Set a -> Set a+deleteAll :: Ord a => a -> Set a -> Set a+deleteSeq :: (Ord a,S.Sequence seq) => seq a -> Set a -> Set a+null :: Set a -> Bool+size :: Set a -> Int+member :: Ord a => a -> Set a -> Bool+count :: Ord a => a -> Set a -> Int+strict :: Ord a => Set a -> Set a++toSeq :: (Ord a,S.Sequence seq) => Set a -> seq a+lookup :: Ord a => a -> Set a -> a+lookupM :: (Ord a,Monad m) => a -> Set a -> m a+lookupAll :: (Ord a,S.Sequence seq) => a -> Set a -> seq a+lookupWithDefault :: Ord a => a -> a -> Set a -> a+fold :: (a -> b -> b) -> b -> Set a -> b+fold1 :: (a -> a -> a) -> Set a -> a+fold' :: (a -> b -> b) -> b -> Set a -> b+fold1' :: (a -> a -> a) -> Set a -> a+filter :: Ord a => (a -> Bool) -> Set a -> Set a+partition :: Ord a => (a -> Bool) -> Set a -> (Set a, Set a)+strictWith :: Ord a => (a -> b) -> Set a -> Set a++deleteMin :: Ord a => Set a -> Set a+deleteMax :: Ord a => Set a -> Set a+unsafeInsertMin :: Ord a => a -> Set a -> Set a+unsafeInsertMax :: Ord a => a -> Set a -> Set a+unsafeFromOrdSeq :: (Ord a,S.Sequence seq) => seq a -> Set a+unsafeAppend :: Ord a => Set a -> Set a -> Set a+filterLT :: Ord a => a -> Set a -> Set a+filterLE :: Ord a => a -> Set a -> Set a+filterGT :: Ord a => a -> Set a -> Set a+filterGE :: Ord a => a -> Set a -> Set a+partitionLT_GE :: Ord a => a -> Set a -> (Set a, Set a)+partitionLE_GT :: Ord a => a -> Set a -> (Set a, Set a)+partitionLT_GT :: Ord a => a -> Set a -> (Set a, Set a)++minView :: (Ord a,Monad m) => Set a -> m (a, Set a)+minElem :: Set a -> a+maxView :: (Ord a,Monad m) => Set a -> m (a, Set a)+maxElem :: Set a -> a+foldr :: (a -> b -> b) -> b -> Set a -> b+foldl :: (b -> a -> b) -> b -> Set a -> b+foldr1 :: (a -> a -> a) -> Set a -> a+foldl1 :: (a -> a -> a) -> Set a -> a+foldr' :: (a -> b -> b) -> b -> Set a -> b+foldl' :: (b -> a -> b) -> b -> Set a -> b+foldr1' :: (a -> a -> a) -> Set a -> a+foldl1' :: (a -> a -> a) -> Set a -> a+toOrdSeq :: (Ord a,S.Sequence seq) => Set a -> seq a++intersection :: Ord a => Set a -> Set a -> Set a+difference :: Ord a => Set a -> Set a -> Set a+symmetricDifference :: Ord a => Set a -> Set a -> Set a+properSubset :: Ord a => Set a -> Set a -> Bool+subset :: Ord a => Set a -> Set a -> Bool++fromSeqWith :: (Ord a,S.Sequence seq) => (a -> a -> a) -> seq a -> Set a+insertWith :: Ord a => (a -> a -> a) -> a -> Set a -> Set a+insertSeqWith :: (Ord a,S.Sequence seq) => (a -> a -> a) -> seq a -> Set a -> Set a+unionl :: Ord a => Set a -> Set a -> Set a+unionr :: Ord a => Set a -> Set a -> Set a+unionWith :: Ord a => (a -> a -> a) -> Set a -> Set a -> Set a+unionSeqWith :: (Ord a,S.Sequence seq) => (a -> a -> a) -> seq (Set a) -> Set a+intersectionWith :: Ord a => (a -> a -> a) -> Set a -> Set a -> Set a+unsafeMapMonotonic :: Ord a => (a -> a) -> Set a -> Set a++moduleName = "Data.Edison.Coll.StandardSet"++type Set = DS.Set++structuralInvariant :: Ord a => Set a -> Bool+structuralInvariant = DS.valid++empty = DS.empty+singleton = DS.singleton+fromSeq = fromSeqUsingFoldr+insert = DS.insert+insertSeq = insertSeqUsingUnion+union = DS.union+unionSeq seq = DS.unions (S.toList seq)+delete = DS.delete+deleteAll = DS.delete -- by set property+deleteSeq = deleteSeqUsingDelete+null = DS.null+size = DS.size+member = DS.member+count = countUsingMember+strict xs = DS.fold (flip const) () xs `seq` xs++toSeq = toSeqUsingFold+lookup el set = DS.findMin (DS.intersection set (DS.singleton el))+lookupM = lookupMUsingLookupAll+lookupAll el set = toSeqUsingFold (DS.intersection set (DS.singleton el))+lookupWithDefault = lookupWithDefaultUsingLookupAll+fold = DS.fold+fold' f x xs = L.foldl' (flip f) x (DS.toList xs)+fold1 f set = let (x,s) = DS.deleteFindMin set in DS.fold f x s+fold1' f xs = L.foldl1' (flip f) (DS.toList xs)+filter = DS.filter+partition = DS.partition+strictWith f xs = DS.fold (\x z -> f x `seq` z) () xs `seq` xs++deleteMin = DS.deleteMin+deleteMax = DS.deleteMax+unsafeInsertMin = DS.insert+unsafeInsertMax = DS.insert+unsafeFromOrdSeq = DS.fromDistinctAscList . S.toList+unsafeAppend = DS.union+filterLT x = fst . DS.split x+filterLE x = DS.filter (<=x)+filterGT x = snd . DS.split x+filterGE x = DS.filter (>=x)+partitionLT_GE x = DS.partition (<x)+partitionLE_GT x = DS.partition (<=x)+partitionLT_GT = DS.split++minView set = if DS.null set + then fail (moduleName ++ ".minView: failed")+ else return (DS.deleteFindMin set)+minElem = DS.findMin++maxView set = if DS.null set+ then fail (moduleName ++ ".maxView: failed")+ else return (DS.deleteFindMax set)+maxElem = DS.findMax++foldr f x set = L.foldr f x (DS.toAscList set)+foldr' f x set = L.foldr' f x (DS.toAscList set)+foldr1 f set = L.foldr1 f (DS.toAscList set)+foldr1' f set = L.foldr1' f (DS.toAscList set)+foldl f x set = L.foldl f x (DS.toAscList set)+foldl' f x set = L.foldl' f x (DS.toAscList set)+foldl1 f set = L.foldl1 f (DS.toAscList set)+foldl1' f set = L.foldl1' f (DS.toAscList set)++toOrdSeq = S.fromList . DS.toAscList++intersection = DS.intersection+difference = DS.difference+symmetricDifference = symmetricDifferenceUsingDifference+properSubset = DS.isProperSubsetOf+subset = DS.isSubsetOf++fromSeqWith = fromSeqWithUsingInsertWith+insertWith f x set = case lookupM x set of + Nothing -> DS.insert x set+ Just x' -> DS.insert (f x x') set+insertSeqWith = insertSeqWithUsingInsertWith+unionl = DS.union+unionr = flip DS.union+unionWith = unionWithUsingOrdLists+unionSeqWith = unionSeqWithUsingReducer+intersectionWith = intersectionWithUsingOrdLists+unsafeMapMonotonic = DS.mapMonotonic++++instance Ord a => C.CollX (Set a) a where+ {singleton = singleton; fromSeq = fromSeq; insert = insert;+ insertSeq = insertSeq; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq;+ null = null; size = size; member = member; count = count;+ strict = strict;+ structuralInvariant = structuralInvariant; instanceName c = moduleName}++instance Ord a => C.OrdCollX (Set a) a where+ {deleteMin = deleteMin; deleteMax = deleteMax; + unsafeInsertMin = unsafeInsertMin; unsafeInsertMax = unsafeInsertMax; + unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend; + filterLT = filterLT; filterLE = filterLE; filterGT = filterGT; + filterGE = filterGE; partitionLT_GE = partitionLT_GE; + partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance Ord a => C.Coll (Set a) a where+ {toSeq = toSeq; lookup = lookup; lookupM = lookupM; + lookupAll = lookupAll; lookupWithDefault = lookupWithDefault; + fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; strictWith = strictWith}++instance Ord a => C.OrdColl (Set a) a where+ {minView = minView; minElem = minElem; maxView = maxView; + maxElem = maxElem; foldr = foldr; foldr' = foldr'; foldl = foldl;+ foldl' = foldl'; foldr1 = foldr1; foldr1' = foldr1';+ foldl1 = foldl1; foldl1' = foldl1'; toOrdSeq = toOrdSeq;+ unsafeMapMonotonic = unsafeMapMonotonic }++instance Ord a => C.SetX (Set a) a where+ {intersection = intersection; difference = difference;+ symmetricDifference = symmetricDifference;+ properSubset = properSubset; subset = subset}++instance Ord a => C.Set (Set a) a where+ {fromSeqWith = fromSeqWith; insertWith = insertWith; + insertSeqWith = insertSeqWith; unionl = unionl; unionr = unionr;+ unionWith = unionWith; unionSeqWith = unionSeqWith;+ intersectionWith = intersectionWith}++instance Ord a => C.OrdSetX (Set a) a++instance Ord a => C.OrdSet (Set a) a+++instance (Ord a, Arbitrary a) => Arbitrary (Set a) where+ arbitrary = do xs <- arbitrary+ return (Prelude.foldr insert empty xs)++ coarbitrary set = coarbitrary (C.toList set)
+ src/Data/Edison/Coll/UnbalancedSet.hs view
@@ -0,0 +1,439 @@+-- |+-- Module : Data.Edison.Coll.UnbalancedSet+-- 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)+--+-- Sets implemented as unbalanced binary search trees.++module Data.Edison.Coll.UnbalancedSet (+ -- * Set type+ Set, -- instance of Coll/CollX, OrdColl/OrdCollX, Set/SetX, OrdSet/OrdSetX++ -- * CollX operations+ empty,singleton,fromSeq,insert,insertSeq,union,unionSeq,delete,deleteAll,+ deleteSeq,null,size,member,count,strict,structuralInvariant,++ -- * Coll operations+ toSeq,lookup,lookupM,lookupAll,lookupWithDefault,fold,fold',+ fold1,fold1',filter,partition,strictWith,++ -- * OrdCollX operations+ deleteMin,deleteMax,unsafeInsertMin,unsafeInsertMax,unsafeFromOrdSeq,+ unsafeAppend,filterLT,filterLE,filterGT,filterGE,partitionLT_GE,+ partitionLE_GT,partitionLT_GT,++ -- * OrdColl operations+ minView,minElem,maxView,maxElem,foldr,foldr',foldl,foldl',+ foldr1,foldr1',foldl1,foldl1',toOrdSeq,unsafeMapMonotonic,++ -- * SetX operations+ intersection,difference,symmetricDifference,properSubset,subset,++ -- * Set operations+ fromSeqWith,insertWith,insertSeqWith,unionl,unionr,unionWith,+ unionSeqWith,intersectionWith,++ -- * Documentation+ moduleName+) where++import Prelude hiding (null,foldr,foldl,foldr1,foldl1,lookup,filter)+import qualified Prelude+import Data.Edison.Prelude+import qualified Data.Edison.Coll as C+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Seq.ListSeq as L+import Data.Edison.Coll.Defaults+import Data.Monoid+import Test.QuickCheck++-- signatures for exported functions+moduleName :: String+empty :: Set a+singleton :: a -> Set a+fromSeq :: (Ord a,S.Sequence seq) => seq a -> Set a+insert :: Ord a => a -> Set a -> Set a+insertSeq :: (Ord a,S.Sequence seq) => seq a -> Set a -> Set a+union :: Ord a => Set a -> Set a -> Set a+unionSeq :: (Ord a,S.Sequence seq) => seq (Set a) -> Set a+delete :: Ord a => a -> Set a -> Set a+deleteAll :: Ord a => a -> Set a -> Set a+deleteSeq :: (Ord a,S.Sequence seq) => seq a -> Set a -> Set a+null :: Set a -> Bool+size :: Set a -> Int+member :: Ord a => a -> Set a -> Bool+count :: Ord a => a -> Set a -> Int+strict :: Set a -> Set a++toSeq :: (Ord a,S.Sequence seq) => Set a -> seq a+lookup :: Ord a => a -> Set a -> a+lookupM :: (Ord a,Monad m) => a -> Set a -> m a+lookupAll :: (Ord a,S.Sequence seq) => a -> Set a -> seq a+lookupWithDefault :: Ord a => a -> a -> Set a -> a+fold :: (a -> b -> b) -> b -> Set a -> b+fold1 :: (a -> a -> a) -> Set a -> a+fold' :: (a -> b -> b) -> b -> Set a -> b+fold1' :: (a -> a -> a) -> Set a -> a+filter :: Ord a => (a -> Bool) -> Set a -> Set a+partition :: Ord a => (a -> Bool) -> Set a -> (Set a, Set a)+strictWith :: (a -> b) -> Set a -> Set a++deleteMin :: Ord a => Set a -> Set a+deleteMax :: Ord a => Set a -> Set a+unsafeInsertMin :: Ord a => a -> Set a -> Set a+unsafeInsertMax :: Ord a => a -> Set a -> Set a+unsafeFromOrdSeq :: (Ord a,S.Sequence seq) => seq a -> Set a+unsafeAppend :: Ord a => Set a -> Set a -> Set a+filterLT :: Ord a => a -> Set a -> Set a+filterLE :: Ord a => a -> Set a -> Set a+filterGT :: Ord a => a -> Set a -> Set a+filterGE :: Ord a => a -> Set a -> Set a+partitionLT_GE :: Ord a => a -> Set a -> (Set a, Set a)+partitionLE_GT :: Ord a => a -> Set a -> (Set a, Set a)+partitionLT_GT :: Ord a => a -> Set a -> (Set a, Set a)++minView :: (Monad m) => Set a -> m (a, Set a)+minElem :: Set a -> a+maxView :: (Monad m) => Set a -> m (a, Set a)+maxElem :: Set a -> a+foldr :: (a -> b -> b) -> b -> Set a -> b+foldl :: (b -> a -> b) -> b -> Set a -> b+foldr1 :: (a -> a -> a) -> Set a -> a+foldl1 :: (a -> a -> a) -> Set a -> a+foldr' :: (a -> b -> b) -> b -> Set a -> b+foldl' :: (b -> a -> b) -> b -> Set a -> b+foldr1' :: (a -> a -> a) -> Set a -> a+foldl1' :: (a -> a -> a) -> Set a -> a+toOrdSeq :: (Ord a,S.Sequence seq) => Set a -> seq a++intersection :: Ord a => Set a -> Set a -> Set a+difference :: Ord a => Set a -> Set a -> Set a+symmetricDifference :: Ord a => Set a -> Set a -> Set a+properSubset :: Ord a => Set a -> Set a -> Bool+subset :: Ord a => Set a -> Set a -> Bool++fromSeqWith :: (Ord a,S.Sequence seq) => (a -> a -> a) -> seq a -> Set a+insertWith :: Ord a => (a -> a -> a) -> a -> Set a -> Set a+insertSeqWith :: (Ord a,S.Sequence seq) => (a -> a -> a) -> seq a -> Set a -> Set a+unionl :: Ord a => Set a -> Set a -> Set a+unionr :: Ord a => Set a -> Set a -> Set a+unionWith :: Ord a => (a -> a -> a) -> Set a -> Set a -> Set a+unionSeqWith :: (Ord a,S.Sequence seq) => (a -> a -> a) -> seq (Set a) -> Set a+intersectionWith :: Ord a => (a -> a -> a) -> Set a -> Set a -> Set a+unsafeMapMonotonic :: Ord a => (a -> a) -> Set a -> Set a++moduleName = "Data.Edison.Coll.UnbalancedSet"++data Set a = E | T (Set a) a (Set a)++-- invariants:+-- * Binary Search Tree order+structuralInvariant :: Ord a => Set a -> Bool+structuralInvariant t = bounded Nothing Nothing t+ where bounded _ _ E = True+ bounded lo hi (T l x r) = cmp_l lo x + && cmp_r x hi+ && bounded lo (Just x) l+ && bounded (Just x) hi r++ cmp_l Nothing _ = True+ cmp_l (Just x) y = x < y++ cmp_r _ Nothing = True+ cmp_r x (Just y) = x < y++++empty = E+singleton x = T E x E++insertWith c x = ins+ where ins E = T E x E+ ins (T a y b) =+ case compare x y of+ LT -> T (ins a) y b+ EQ -> T a (c x y) b+ GT -> T a y (ins b)++delete x E = E+delete x (T a y b) =+ case compare x y of+ LT -> T (delete x a) y b+ EQ -> unsafeAppend a b+ GT -> T a y (delete x b)++null E = True+null (T _ _ _) = False++size t = sz t 0+ where sz E i = i+ sz (T a x b) i = sz a (sz b (i+1))++member x E = False+member x (T a y b) =+ case compare x y of+ LT -> member x a+ EQ -> True+ GT -> member x b++lookupM x E = fail "UnbalancedSet.lookupM: XXX"+lookupM x (T a y b) =+ case compare x y of+ LT -> lookupM x a+ EQ -> return y+ GT -> lookupM x b++fold f e E = e+fold f e (T a x b) = f x (fold f (fold f e a) b)++fold' f e E = e+fold' f e (T a x b) = e `seq` f x $! (fold' f (fold' f e a) b)++fold1 f E = error "UnbalancedSet.fold1: empty collection"+fold1 f (T a x b) = fold f (fold f x a) b++fold1' f E = error "UnbalancedSet.fold1': empty collection"+fold1' f (T a x b) = fold' f (fold' f x a) b++deleteMin E = E+deleteMin (T E x b) = b+deleteMin (T a x b) = T (deleteMin a) x b++deleteMax E = E+deleteMax (T a x E) = a+deleteMax (T a x b) = T a x (deleteMax b)++unsafeInsertMin x t = T E x t+unsafeInsertMax x t = T t x E++unsafeFromOrdSeq xs = fst (ins xs (S.size xs))+ where ins xs 0 = (E,xs)+ ins xs n = let m = n `div` 2+ (a,xs') = ins xs m+ Just (x,xs'') = S.lview xs'+ (b,xs''') = ins xs'' (n - m - 1)+ in (T a x b,xs''')++unsafeAppend a b = case minView b of+ Nothing -> a+ Just (x,b') -> T a x b'++filterLT y E = E+filterLT y (T a x b) =+ case compare x y of+ LT -> T a x (filterLT y b)+ EQ -> a+ GT -> filterLT y a++filterLE y E = E+filterLE y (T a x b) =+ case compare x y of+ LT -> T a x (filterLE y b)+ EQ -> T a x E+ GT -> filterLE y a++filterGT y E = E+filterGT y (T a x b) =+ case compare x y of+ LT -> filterGT y b+ EQ -> b+ GT -> T (filterGT y a) x b++filterGE y E = E+filterGE y (T a x b) =+ case compare x y of+ LT -> filterGE y b+ EQ -> T E x b+ GT -> T (filterGE y a) x b++partitionLT_GE y E = (E,E)+partitionLT_GE y (T a x b) =+ case compare x y of+ LT -> (T a x b0,b1)+ where (b0,b1) = partitionLT_GE y b+ EQ -> (a,T E x b)+ GT -> (a0,T a1 x b)+ where (a0,a1) = partitionLT_GE y a++partitionLE_GT y E = (E,E)+partitionLE_GT y (T a x b) =+ case compare x y of+ LT -> (T a x b0,b1)+ where (b0,b1) = partitionLE_GT y b+ EQ -> (T a x E,b)+ GT -> (a0,T a1 x b)+ where (a0,a1) = partitionLE_GT y a++partitionLT_GT y E = (E,E)+partitionLT_GT y (T a x b) =+ case compare x y of+ LT -> (T a x b0,b1)+ where (b0,b1) = partitionLT_GT y b+ EQ -> (a,b)+ GT -> (a0,T a1 x b)+ where (a0,a1) = partitionLT_GT y a++minView E = fail "UnbalancedSet.minView: empty collection"+minView (T E x b) = return (x, b)+minView (T a x b) = return (y, T a' x b)+ where Just (y,a') = minView a++minElem E = error "UnbalancedSet.minElem: empty collection"+minElem (T E x b) = x+minElem (T a x b) = minElem a++maxView E = fail "UnbalancedSet.maxView: empty collection"+maxView (T a x E) = return (x, a)+maxView (T a x b) = return (y, T a x b')+ where Just (y, b') = maxView b++maxElem E = error "UnbalancedSet.maxElem: empty collection"+maxElem (T a x E) = x+maxElem (T a x b) = maxElem b++foldr f e E = e+foldr f e (T a x b) = foldr f (f x (foldr f e b)) a++foldr' f e E = e+foldr' f e (T a x b) = e `seq` foldr' f (f x $! (foldr' f e b)) a++foldl f e E = e+foldl f e (T a x b) = foldl f (f (foldl f e a) x) b++foldl' f e E = e+foldl' f e (T a x b) = e `seq` foldl' f ((f $! (foldl' f e a)) x) b++foldr1 f E = error "UnbalancedSet.foldr1: empty collection"+foldr1 f (T a x E) = foldr f x a+foldr1 f (T a x b) = foldr f (f x (foldr1 f b)) a++foldr1' f E = error "UnbalancedSet.foldr1': empty collection"+foldr1' f (T a x E) = foldr' f x a+foldr1' f (T a x b) = foldr' f (f x $! (foldr1' f b)) a++foldl1 f E = error "UnbalancedSet.foldl1: empty collection"+foldl1 f (T E x b) = foldl f x b+foldl1 f (T a x b) = foldl f (f (foldl1 f a) x) b++foldl1' f E = error "UnbalancedSet.foldl1': empty collection"+foldl1' f (T E x b) = foldl' f x b+foldl1' f (T a x b) = foldl' f ((f $! (foldl1' f a)) x) b++unsafeMapMonotonic f E = E+unsafeMapMonotonic f (T a x b) = + T (unsafeMapMonotonic f a) (f x) (unsafeMapMonotonic f b)++strict s@E = s+strict s@(T l x r) = strict l `seq` strict r `seq` s++strictWith f s@E = s+strictWith f s@(T l x r) = f x `seq` strictWith f l `seq` strictWith f r `seq` s++-- the remaining functions all use default definitions++fromSeq = fromSeqUsingUnionSeq+insert = insertUsingInsertWith+insertSeq = insertSeqUsingUnion+union = unionUsingUnionWith+unionSeq = unionSeqUsingReduce+deleteAll = delete+deleteSeq = deleteSeqUsingDelete+count = countUsingMember++toSeq = toSeqUsingFold+lookup = lookupUsingLookupM+lookupAll = lookupAllUsingLookupM+lookupWithDefault = lookupWithDefaultUsingLookupM+filter = filterUsingOrdLists+partition = partitionUsingOrdLists+toOrdSeq = toOrdSeqUsingFoldr++intersection = intersectionUsingIntersectionWith+difference = differenceUsingOrdLists+symmetricDifference = symmetricDifferenceUsingDifference+properSubset = properSubsetUsingOrdLists+subset = subsetUsingOrdLists+fromSeqWith = fromSeqWithUsingInsertWith+insertSeqWith = insertSeqWithUsingInsertWith+unionl = unionlUsingUnionWith+unionr = unionrUsingUnionWith+unionWith = unionWithUsingOrdLists+unionSeqWith = unionSeqWithUsingReducer+intersectionWith = intersectionWithUsingOrdLists++-- instance declarations++instance Ord a => C.CollX (Set a) a where+ {singleton = singleton; fromSeq = fromSeq; insert = insert;+ insertSeq = insertSeq; unionSeq = unionSeq; + delete = delete; deleteAll = deleteAll; deleteSeq = deleteSeq;+ null = null; size = size; member = member; count = count;+ strict = strict;+ structuralInvariant = structuralInvariant; instanceName c = moduleName}++instance Ord a => C.OrdCollX (Set a) a where+ {deleteMin = deleteMin; deleteMax = deleteMax; + unsafeInsertMin = unsafeInsertMin; unsafeInsertMax = unsafeInsertMax; + unsafeFromOrdSeq = unsafeFromOrdSeq; unsafeAppend = unsafeAppend; + filterLT = filterLT; filterLE = filterLE; filterGT = filterGT; + filterGE = filterGE; partitionLT_GE = partitionLT_GE; + partitionLE_GT = partitionLE_GT; partitionLT_GT = partitionLT_GT}++instance Ord a => C.Coll (Set a) a where+ {toSeq = toSeq; lookup = lookup; lookupM = lookupM; + lookupAll = lookupAll; lookupWithDefault = lookupWithDefault; + fold = fold; fold' = fold'; fold1 = fold1; fold1' = fold1';+ filter = filter; partition = partition; strictWith = strictWith}++instance Ord a => C.OrdColl (Set a) a where+ {minView = minView; minElem = minElem; maxView = maxView; + maxElem = maxElem; foldr = foldr; foldr' = foldr'; + foldl = foldl; foldl' = foldl'; foldr1 = foldr1; foldr1' = foldr1';+ foldl1 = foldl1; foldl1' = foldl1'; toOrdSeq = toOrdSeq;+ unsafeMapMonotonic = unsafeMapMonotonic}++instance Ord a => C.SetX (Set a) a where+ {intersection = intersection; difference = difference;+ symmetricDifference = symmetricDifference;+ properSubset = properSubset; subset = subset}++instance Ord a => C.Set (Set a) a where+ {fromSeqWith = fromSeqWith; insertWith = insertWith; + insertSeqWith = insertSeqWith; unionl = unionl; unionr = unionr;+ unionWith = unionWith; unionSeqWith = unionSeqWith;+ intersectionWith = intersectionWith}++instance Ord a => C.OrdSetX (Set a) a++instance Ord a => C.OrdSet (Set a) a+++instance Ord a => Eq (Set a) where+ xs == ys = C.toOrdList xs == C.toOrdList ys++instance (Ord a, Show a) => Show (Set a) where+ showsPrec = showsPrecUsingToList++instance (Ord a, Read a) => Read (Set a) where+ readsPrec = readsPrecUsingFromList+++instance (Ord a, Arbitrary a) => Arbitrary (Set a) where+ arbitrary = do xs <- arbitrary+ return (Prelude.foldr insert empty xs)++ coarbitrary E = variant 0+ coarbitrary (T a x b) = + variant 1 . coarbitrary a . coarbitrary x . coarbitrary b++instance (Ord a) => Monoid (Set a) where+ mempty = empty+ mappend = union+ mconcat = unionSeq++instance (Ord a) => Ord (Set a) where+ compare = compareUsingToOrdList
+ src/Data/Edison/Concrete/FingerTree.hs view
@@ -0,0 +1,773 @@+-----------------------------------------------------------------------------+-- |+-- Module : Data.Edison.Concrete.FingerTree+-- Copyright : (c) Ross Paterson, Ralf Hinze 2006+-- License : BSD-style+-- Maintainer : robdockins AT fastmail DOT fm+-- Stability : internal (non-stable)+-- Portability : non-portable (MPTCs and functional dependencies)+--+-- A general sequence representation with arbitrary annotations, for+-- use as a base for implementations of various collection types, as+-- described in section 4 of+--+-- * Ralf Hinze and Ross Paterson,+-- \"Finger trees: a simple general-purpose data structure\",+-- /Journal of Functional Programming/ 16:2 (2006) pp 197-217.+-- <http://www.soi.city.ac.uk/~ross/papers/FingerTree.html>+--+-- This data structure forms the basis of the "Data.Edison.Seq.FingerSeq"+-- sequence data structure.+--+-- An amortized running time is given for each operation, with /n/+-- referring to the length of the sequence. These bounds hold even in+-- a persistent (shared) setting.+--+-----------------------------------------------------------------------------++{------------------------------------------------------------------++Copyright 2004, The University Court of the University of Glasgow. +All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++- Redistributions of source code must retain the above copyright notice,+this list of conditions and the following disclaimer.+ +- Redistributions in binary form must reproduce the above copyright notice,+this list of conditions and the following disclaimer in the documentation+and/or other materials provided with the distribution.+ +- Neither name of the University nor the names of its contributors may be+used to endorse or promote products derived from this software without+specific prior written permission. ++THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF+GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE+UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+DAMAGE.++-----------------------------------------------------------------------------}+++module Data.Edison.Concrete.FingerTree (+ FingerTree,+ Split(..),++ empty, singleton, lcons, rcons, append,+ fromList, toList, null, size, lview, rview,+ split, takeUntil, dropUntil, splitTree,+ reverse, mapTree, foldFT, reduce1, reduce1',+ strict, strictWith, structuralInvariant++ -- traverse'+ ) where++import Prelude hiding (null, reverse)+import Data.Monoid+import Test.QuickCheck++import Data.Edison.Prelude+++infixr 5 `lcons`+infixl 5 `rcons0`++data Digit a+ = One a+ | Two a a+ | Three a a a+ | Four a a a a+ deriving Show++foldDigit :: (b -> b -> b) -> (a -> b) -> Digit a -> b+foldDigit mapp f (One a) = f a+foldDigit mapp f (Two a b) = f a `mapp` f b+foldDigit mapp f (Three a b c) = f a `mapp` f b `mapp` f c+foldDigit mapp f (Four a b c d) = f a `mapp` f b `mapp` f c `mapp` f d++reduceDigit :: (b -> b -> b) -> (a -> b) -> Digit a -> b+reduceDigit mapp f (One a) = f a+reduceDigit mapp f (Two a b) = f a `mapp` f b+reduceDigit mapp f (Three a b c) = f a `mapp` f b `mapp` f c+reduceDigit mapp f (Four a b c d) = (f a `mapp` f b) `mapp` (f c `mapp` f d)++digitToList :: Digit a -> [a] -> [a]+digitToList (One a) xs = a : xs+digitToList (Two a b) xs = a : b : xs+digitToList (Three a b c) xs = a : b : c : xs+digitToList (Four a b c d) xs = a : b : c : d : xs++sizeDigit :: (a -> Int) -> Digit a -> Int+sizeDigit f (One x) = f x+sizeDigit f (Two x y) = f x + f y+sizeDigit f (Three x y z) = f x + f y + f z+sizeDigit f (Four x y z w) = f x + f y + f z + f w++instance (Measured v a) => Measured v (Digit a) where+ measure = foldDigit mappend measure++data Node v a = Node2 !v a a | Node3 !v a a a+ deriving Show++sizeNode :: (a -> Int) -> Node v a -> Int+sizeNode f (Node2 _ x y) = f x + f y+sizeNode f (Node3 _ x y z) = f x + f y + f z++foldNode :: (b -> b -> b) -> (a -> b) -> Node v a -> b+foldNode mapp f (Node2 _ a b) = f a `mapp` f b+foldNode mapp f (Node3 _ a b c) = f a `mapp` f b `mapp` f c++nodeToList :: Node v a -> [a] -> [a]+nodeToList (Node2 _ a b) xs = a : b : xs+nodeToList (Node3 _ a b c) xs = a : b : c : xs++node2 :: (Measured v a) => a -> a -> Node v a+node2 a b = Node2 (measure a `mappend` measure b) a b++node3 :: (Measured v a) => a -> a -> a -> Node v a+node3 a b c = Node3 (measure a `mappend` measure b `mappend` measure c) a b c++instance (Monoid v) => Measured v (Node v a) where+ measure (Node2 v _ _) = v+ measure (Node3 v _ _ _) = v++nodeToDigit :: Node v a -> Digit a+nodeToDigit (Node2 _ a b) = Two a b+nodeToDigit (Node3 _ a b c) = Three a b c+++-- | Finger trees with element type @a@, annotated with measures of type @v@.+-- The operations enforce the constraint @'Measured' v a@.+data FingerTree v a+ = Empty+ | Single a+ | Deep !v !(Digit a) (FingerTree v (Node v a)) !(Digit a)++deep :: (Measured v a) =>+ Digit a -> FingerTree v (Node v a) -> Digit a -> FingerTree v a+deep pr m sf = Deep ((measure pr `mappendVal` m) `mappend` measure sf) pr m sf++structuralInvariant :: (Eq v, Measured v a) => FingerTree v a -> Bool+structuralInvariant Empty = True+structuralInvariant (Single _) = True+structuralInvariant (Deep v pr m sf) =+ v == foldDigit mappend measure pr `mappend`+ foldFT mempty mappend (foldNode mappend measure) m `mappend`+ foldDigit mappend measure sf++instance (Measured v a) => Measured v (FingerTree v a) where+ measure Empty = mempty+ measure (Single x) = measure x+ measure (Deep v _ _ _) = v++sizeFT :: (a -> Int) -> FingerTree v a -> Int+sizeFT f Empty = 0+sizeFT f (Single x) = f x+sizeFT f (Deep _ d1 m d2) = sizeDigit f d1 + sizeFT (sizeNode f) m + sizeDigit f d2++size :: FingerTree v a -> Int+size = sizeFT (const 1)++foldFT :: b -> (b -> b -> b) -> (a -> b) -> FingerTree v a -> b+foldFT mz mapp _ Empty = mz+foldFT mz mapp f (Single x) = f x+foldFT mz mapp f (Deep _ pr m sf) =+ foldDigit mapp f pr `mapp` foldFT mz mapp (foldNode mapp f) m `mapp` foldDigit mapp f sf++ftToList :: FingerTree v a -> [a] -> [a]+ftToList Empty xs = xs+ftToList (Single a) xs = a : xs+ftToList (Deep _ d1 ft d2) xs = digitToList d1 (foldr nodeToList [] . ftToList ft $ []) ++ (digitToList d2 xs)++toList :: FingerTree v a -> [a]+toList ft = ftToList ft []++reduce1_aux :: (b -> b -> b) -> (a -> b) -> Digit a -> FingerTree v (Node v a) -> Digit a -> b+reduce1_aux mapp f pr Empty sf = + (reduceDigit mapp f pr) `mapp`+ (reduceDigit mapp f sf)++reduce1_aux mapp f pr (Single x) sf =+ (reduceDigit mapp f pr) `mapp`+ (foldNode mapp f x) `mapp`+ (reduceDigit mapp f sf)++reduce1_aux mapp f pr (Deep _ pr' m sf') sf =+ (reduceDigit mapp f pr) `mapp` + (reduce1_aux mapp+ (foldNode mapp f)+ pr' m sf') `mapp`+ (reduceDigit mapp f sf)++reduce1 :: (a -> a -> a) -> FingerTree v a -> a+reduce1 mapp Empty = error "FingerTree.reduce1: empty tree"+reduce1 mapp (Single x) = x+reduce1 mapp (Deep _ pr m sf) = reduce1_aux mapp id pr m sf++reduce1' :: (a -> a -> a) -> FingerTree v a -> a +reduce1' mapp Empty = error "FingerTree.reduce1': empty tree"+reduce1' mapp (Single x) = x+reduce1' mapp (Deep _ pr m sf) = reduce1_aux mapp' id pr m sf+ where mapp' x y = x `seq` y `seq` mapp x y+++strict :: FingerTree v a -> FingerTree v a+strict xs = foldFT () seq (const ()) xs `seq` xs++strictWith :: (a -> b) -> FingerTree v a -> FingerTree v a+strictWith f xs = foldFT () seq (\x -> f x `seq` ()) xs `seq` xs++instance (Measured v a, Eq a) => Eq (FingerTree v a) where+ xs == ys = toList xs == toList ys++instance (Measured v a, Ord a) => Ord (FingerTree v a) where+ compare xs ys = compare (toList xs) (toList ys)++instance (Measured v a, Show a) => Show (FingerTree v a) where+ showsPrec p xs = showParen (p > 10) $+ showString "fromList " . shows (toList xs)++mapTree :: (Measured v2 a2) =>+ (a1 -> a2) -> FingerTree v1 a1 -> FingerTree v2 a2+mapTree _ Empty = Empty+mapTree f (Single x) = Single (f x)+mapTree f (Deep _ pr m sf) =+ deep (mapDigit f pr) (mapTree (mapNode f) m) (mapDigit f sf)++mapNode :: (Measured v2 a2) =>+ (a1 -> a2) -> Node v1 a1 -> Node v2 a2+mapNode f (Node2 _ a b) = node2 (f a) (f b)+mapNode f (Node3 _ a b c) = node3 (f a) (f b) (f c)++mapDigit :: (a -> b) -> Digit a -> Digit b+mapDigit f (One a) = One (f a)+mapDigit f (Two a b) = Two (f a) (f b)+mapDigit f (Three a b c) = Three (f a) (f b) (f c)+mapDigit f (Four a b c d) = Four (f a) (f b) (f c) (f d)+++{-+-- | Like 'traverse', but with a more constrained type.+traverse' :: (Measured v1 a1, Measured v2 a2, Applicative f) =>+ (a1 -> f a2) -> FingerTree v1 a1 -> f (FingerTree v2 a2)+traverse' = traverseTree++traverseTree :: (Measured v2 a2, Applicative f) =>+ (a1 -> f a2) -> FingerTree v1 a1 -> f (FingerTree v2 a2)+traverseTree _ Empty = pure Empty+traverseTree f (Single x) = Single <$> f x+traverseTree f (Deep _ pr m sf) =+ deep <$> traverseDigit f pr <*> traverseTree (traverseNode f) m <*> traverseDigit f sf++traverseNode :: (Measured v2 a2, Applicative f) =>+ (a1 -> f a2) -> Node v1 a1 -> f (Node v2 a2)+traverseNode f (Node2 _ a b) = node2 <$> f a <*> f b+traverseNode f (Node3 _ a b c) = node3 <$> f a <*> f b <*> f c++traverseDigit :: (Applicative f) => (a -> f b) -> Digit a -> f (Digit b)+traverseDigit f (One a) = One <$> f a+traverseDigit f (Two a b) = Two <$> f a <*> f b+traverseDigit f (Three a b c) = Three <$> f a <*> f b <*> f c+traverseDigit f (Four a b c d) = Four <$> f a <*> f b <*> f c <*> f d+-}++-- | /O(1)/. The empty sequence.+empty :: Measured v a => FingerTree v a+empty = Empty++-- | /O(1)/. A singleton sequence.+singleton :: Measured v a => a -> FingerTree v a+singleton = Single++-- | /O(n)/. Create a sequence from a finite list of elements.+fromList :: (Measured v a) => [a] -> FingerTree v a+fromList = foldr lcons Empty++-- | /O(1)/. Add an element to the left end of a sequence.+lcons :: (Measured v a) => a -> FingerTree v a -> FingerTree v a+a `lcons` Empty = Single a+a `lcons` Single b = deep (One a) Empty (One b)+a `lcons` Deep _ (Four b c d e) m sf = m `seq`+ deep (Two a b) (node3 c d e `lcons` m) sf+a `lcons` Deep _ pr m sf = deep (consDigit a pr) m sf++consDigit :: a -> Digit a -> Digit a+consDigit a (One b) = Two a b+consDigit a (Two b c) = Three a b c+consDigit a (Three b c d) = Four a b c d+consDigit _ _ = error "FingerTree.consDigit: bug!"++-- | /O(1)/. Add an element to the right end of a sequence.+rcons :: (Measured v a) => a -> FingerTree v a -> FingerTree v a+rcons = flip rcons0++rcons0 :: (Measured v a) => FingerTree v a -> a -> FingerTree v a+Empty `rcons0` a = Single a+Single a `rcons0` b = deep (One a) Empty (One b)+Deep _ pr m (Four a b c d) `rcons0` e = m `seq`+ deep pr (m `rcons0` node3 a b c) (Two d e)+Deep _ pr m sf `rcons0` x = deep pr m (snocDigit sf x)++snocDigit :: Digit a -> a -> Digit a+snocDigit (One a) b = Two a b+snocDigit (Two a b) c = Three a b c+snocDigit (Three a b c) d = Four a b c d+snocDigit _ _ = error "FingerTree.snocDigit: bug!"++-- | /O(1)/. Is this the empty sequence?+null :: (Measured v a) => FingerTree v a -> Bool+null Empty = True+null _ = False++-- | /O(1)/. Analyse the left end of a sequence.+lview :: (Measured v a, Monad m) => FingerTree v a -> m (a,FingerTree v a)+lview Empty = fail "FingerTree.lview: empty tree"+lview (Single x) = return (x, Empty)+lview (Deep _ (One x) m sf) = return . (,) x $+ case lview m of+ Nothing -> digitToTree sf+ Just (a,m') -> deep (nodeToDigit a) m' sf++lview (Deep _ pr m sf) = return (lheadDigit pr, deep (ltailDigit pr) m sf)++lheadDigit :: Digit a -> a+lheadDigit (One a) = a+lheadDigit (Two a _) = a+lheadDigit (Three a _ _) = a+lheadDigit (Four a _ _ _) = a++ltailDigit :: Digit a -> Digit a+ltailDigit (Two _ b) = One b+ltailDigit (Three _ b c) = Two b c+ltailDigit (Four _ b c d) = Three b c d+ltailDigit _ = error "FingerTree.ltailDigit: bug!"++-- | /O(1)/. Analyse the right end of a sequence.+rview :: (Measured v a, Monad m) => FingerTree v a -> m (a, FingerTree v a)+rview Empty = fail "FingerTree.rview: empty tree"+rview (Single x) = return (x, Empty)+rview (Deep _ pr m (One x)) = return . (,) x $+ case rview m of+ Nothing -> digitToTree pr+ Just (a,m') -> deep pr m' (nodeToDigit a)++rview (Deep _ pr m sf) = return (rheadDigit sf, deep pr m (rtailDigit sf))+++rheadDigit :: Digit a -> a+rheadDigit (One a) = a+rheadDigit (Two _ b) = b+rheadDigit (Three _ _ c) = c+rheadDigit (Four _ _ _ d) = d++rtailDigit :: Digit a -> Digit a+rtailDigit (Two a _) = One a+rtailDigit (Three a b _) = Two a b+rtailDigit (Four a b c _) = Three a b c+rtailDigit _ = error "FingerTree.rtailDigit: bug!"++digitToTree :: (Measured v a) => Digit a -> FingerTree v a+digitToTree (One a) = Single a+digitToTree (Two a b) = deep (One a) Empty (One b)+digitToTree (Three a b c) = deep (Two a b) Empty (One c)+digitToTree (Four a b c d) = deep (Two a b) Empty (Two c d)+++-- | /O(log(min(n1,n2)))/. Concatenate two sequences.+append :: (Measured v a) => FingerTree v a -> FingerTree v a -> FingerTree v a+append = appendTree0++appendTree0 :: (Measured v a) => FingerTree v a -> FingerTree v a -> FingerTree v a+appendTree0 Empty xs =+ xs+appendTree0 xs Empty =+ xs+appendTree0 (Single x) xs =+ x `lcons` xs+appendTree0 xs (Single x) =+ xs `rcons0` x+appendTree0 (Deep _ pr1 m1 sf1) (Deep _ pr2 m2 sf2) =+ deep pr1 (addDigits0 m1 sf1 pr2 m2) sf2++addDigits0 :: (Measured v a) => FingerTree v (Node v a) -> Digit a -> Digit a -> FingerTree v (Node v a) -> FingerTree v (Node v a)+addDigits0 m1 (One a) (One b) m2 =+ appendTree1 m1 (node2 a b) m2+addDigits0 m1 (One a) (Two b c) m2 =+ appendTree1 m1 (node3 a b c) m2+addDigits0 m1 (One a) (Three b c d) m2 =+ appendTree2 m1 (node2 a b) (node2 c d) m2+addDigits0 m1 (One a) (Four b c d e) m2 =+ appendTree2 m1 (node3 a b c) (node2 d e) m2+addDigits0 m1 (Two a b) (One c) m2 =+ appendTree1 m1 (node3 a b c) m2+addDigits0 m1 (Two a b) (Two c d) m2 =+ appendTree2 m1 (node2 a b) (node2 c d) m2+addDigits0 m1 (Two a b) (Three c d e) m2 =+ appendTree2 m1 (node3 a b c) (node2 d e) m2+addDigits0 m1 (Two a b) (Four c d e f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits0 m1 (Three a b c) (One d) m2 =+ appendTree2 m1 (node2 a b) (node2 c d) m2+addDigits0 m1 (Three a b c) (Two d e) m2 =+ appendTree2 m1 (node3 a b c) (node2 d e) m2+addDigits0 m1 (Three a b c) (Three d e f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits0 m1 (Three a b c) (Four d e f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits0 m1 (Four a b c d) (One e) m2 =+ appendTree2 m1 (node3 a b c) (node2 d e) m2+addDigits0 m1 (Four a b c d) (Two e f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits0 m1 (Four a b c d) (Three e f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits0 m1 (Four a b c d) (Four e f g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2++appendTree1 :: (Measured v a) => FingerTree v a -> a -> FingerTree v a -> FingerTree v a+appendTree1 Empty a xs =+ a `lcons` xs+appendTree1 xs a Empty =+ xs `rcons0` a+appendTree1 (Single x) a xs =+ x `lcons` (a `lcons` xs)+appendTree1 xs a (Single x) =+ xs `rcons0` a `rcons0` x+appendTree1 (Deep _ pr1 m1 sf1) a (Deep _ pr2 m2 sf2) =+ deep pr1 (addDigits1 m1 sf1 a pr2 m2) sf2++addDigits1 :: (Measured v a) => FingerTree v (Node v a) -> Digit a -> a -> Digit a -> FingerTree v (Node v a) -> FingerTree v (Node v a)+addDigits1 m1 (One a) b (One c) m2 =+ appendTree1 m1 (node3 a b c) m2+addDigits1 m1 (One a) b (Two c d) m2 =+ appendTree2 m1 (node2 a b) (node2 c d) m2+addDigits1 m1 (One a) b (Three c d e) m2 =+ appendTree2 m1 (node3 a b c) (node2 d e) m2+addDigits1 m1 (One a) b (Four c d e f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits1 m1 (Two a b) c (One d) m2 =+ appendTree2 m1 (node2 a b) (node2 c d) m2+addDigits1 m1 (Two a b) c (Two d e) m2 =+ appendTree2 m1 (node3 a b c) (node2 d e) m2+addDigits1 m1 (Two a b) c (Three d e f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits1 m1 (Two a b) c (Four d e f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits1 m1 (Three a b c) d (One e) m2 =+ appendTree2 m1 (node3 a b c) (node2 d e) m2+addDigits1 m1 (Three a b c) d (Two e f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits1 m1 (Three a b c) d (Three e f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits1 m1 (Three a b c) d (Four e f g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits1 m1 (Four a b c d) e (One f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits1 m1 (Four a b c d) e (Two f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits1 m1 (Four a b c d) e (Three f g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits1 m1 (Four a b c d) e (Four f g h i) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2++appendTree2 :: (Measured v a) => FingerTree v a -> a -> a -> FingerTree v a -> FingerTree v a+appendTree2 Empty a b xs =+ a `lcons` (b `lcons` xs)+appendTree2 xs a b Empty =+ xs `rcons0` a `rcons0` b+appendTree2 (Single x) a b xs =+ x `lcons` (a `lcons` (b `lcons` xs))+appendTree2 xs a b (Single x) =+ xs `rcons0` a `rcons0` b `rcons0` x+appendTree2 (Deep _ pr1 m1 sf1) a b (Deep _ pr2 m2 sf2) =+ deep pr1 (addDigits2 m1 sf1 a b pr2 m2) sf2++addDigits2 :: (Measured v a) => FingerTree v (Node v a) -> Digit a -> a -> a -> Digit a -> FingerTree v (Node v a) -> FingerTree v (Node v a)+addDigits2 m1 (One a) b c (One d) m2 =+ appendTree2 m1 (node2 a b) (node2 c d) m2+addDigits2 m1 (One a) b c (Two d e) m2 =+ appendTree2 m1 (node3 a b c) (node2 d e) m2+addDigits2 m1 (One a) b c (Three d e f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits2 m1 (One a) b c (Four d e f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits2 m1 (Two a b) c d (One e) m2 =+ appendTree2 m1 (node3 a b c) (node2 d e) m2+addDigits2 m1 (Two a b) c d (Two e f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits2 m1 (Two a b) c d (Three e f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits2 m1 (Two a b) c d (Four e f g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits2 m1 (Three a b c) d e (One f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits2 m1 (Three a b c) d e (Two f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits2 m1 (Three a b c) d e (Three f g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits2 m1 (Three a b c) d e (Four f g h i) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2+addDigits2 m1 (Four a b c d) e f (One g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits2 m1 (Four a b c d) e f (Two g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits2 m1 (Four a b c d) e f (Three g h i) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2+addDigits2 m1 (Four a b c d) e f (Four g h i j) m2 =+ appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2++appendTree3 :: (Measured v a) => FingerTree v a -> a -> a -> a -> FingerTree v a -> FingerTree v a+appendTree3 Empty a b c xs =+ a `lcons` (b `lcons` (c `lcons` xs))+appendTree3 xs a b c Empty =+ xs `rcons0` a `rcons0` b `rcons0` c+appendTree3 (Single x) a b c xs =+ x `lcons` (a `lcons` (b `lcons` (c `lcons` xs)))+appendTree3 xs a b c (Single x) =+ xs `rcons0` a `rcons0` b `rcons0` c `rcons0` x+appendTree3 (Deep _ pr1 m1 sf1) a b c (Deep _ pr2 m2 sf2) =+ deep pr1 (addDigits3 m1 sf1 a b c pr2 m2) sf2++addDigits3 :: (Measured v a) => FingerTree v (Node v a) -> Digit a -> a -> a -> a -> Digit a -> FingerTree v (Node v a) -> FingerTree v (Node v a)+addDigits3 m1 (One a) b c d (One e) m2 =+ appendTree2 m1 (node3 a b c) (node2 d e) m2+addDigits3 m1 (One a) b c d (Two e f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits3 m1 (One a) b c d (Three e f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits3 m1 (One a) b c d (Four e f g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits3 m1 (Two a b) c d e (One f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits3 m1 (Two a b) c d e (Two f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits3 m1 (Two a b) c d e (Three f g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits3 m1 (Two a b) c d e (Four f g h i) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2+addDigits3 m1 (Three a b c) d e f (One g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits3 m1 (Three a b c) d e f (Two g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits3 m1 (Three a b c) d e f (Three g h i) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2+addDigits3 m1 (Three a b c) d e f (Four g h i j) m2 =+ appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2+addDigits3 m1 (Four a b c d) e f g (One h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits3 m1 (Four a b c d) e f g (Two h i) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2+addDigits3 m1 (Four a b c d) e f g (Three h i j) m2 =+ appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2+addDigits3 m1 (Four a b c d) e f g (Four h i j k) m2 =+ appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node2 j k) m2++appendTree4 :: (Measured v a) => FingerTree v a -> a -> a -> a -> a -> FingerTree v a -> FingerTree v a+appendTree4 Empty a b c d xs =+ a `lcons` b `lcons` c `lcons` d `lcons` xs+appendTree4 xs a b c d Empty =+ xs `rcons0` a `rcons0` b `rcons0` c `rcons0` d+appendTree4 (Single x) a b c d xs =+ x `lcons` a `lcons` b `lcons` c `lcons` d `lcons` xs+appendTree4 xs a b c d (Single x) =+ xs `rcons0` a `rcons0` b `rcons0` c `rcons0` d `rcons0` x+appendTree4 (Deep _ pr1 m1 sf1) a b c d (Deep _ pr2 m2 sf2) =+ deep pr1 (addDigits4 m1 sf1 a b c d pr2 m2) sf2++addDigits4 :: (Measured v a) => FingerTree v (Node v a) -> Digit a -> a -> a -> a -> a -> Digit a -> FingerTree v (Node v a) -> FingerTree v (Node v a)+addDigits4 m1 (One a) b c d e (One f) m2 =+ appendTree2 m1 (node3 a b c) (node3 d e f) m2+addDigits4 m1 (One a) b c d e (Two f g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits4 m1 (One a) b c d e (Three f g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits4 m1 (One a) b c d e (Four f g h i) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2+addDigits4 m1 (Two a b) c d e f (One g) m2 =+ appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2+addDigits4 m1 (Two a b) c d e f (Two g h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits4 m1 (Two a b) c d e f (Three g h i) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2+addDigits4 m1 (Two a b) c d e f (Four g h i j) m2 =+ appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2+addDigits4 m1 (Three a b c) d e f g (One h) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2+addDigits4 m1 (Three a b c) d e f g (Two h i) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2+addDigits4 m1 (Three a b c) d e f g (Three h i j) m2 =+ appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2+addDigits4 m1 (Three a b c) d e f g (Four h i j k) m2 =+ appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node2 j k) m2+addDigits4 m1 (Four a b c d) e f g h (One i) m2 =+ appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2+addDigits4 m1 (Four a b c d) e f g h (Two i j) m2 =+ appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2+addDigits4 m1 (Four a b c d) e f g h (Three i j k) m2 =+ appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node2 j k) m2+addDigits4 m1 (Four a b c d) e f g h (Four i j k l) m2 =+ appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node3 j k l) m2+++-- | /O(log(min(i,n-i)))/. Split a sequence at a point where the predicate+-- on the accumulated measure changes from 'False' to 'True'.+split :: (Measured v a) =>+ (v -> Bool) -> FingerTree v a -> (FingerTree v a, FingerTree v a)+split _p Empty = (Empty, Empty)+split p xs+ | p (measure xs) = (l, x `lcons` r)+ | otherwise = (xs, Empty)+ where Split l x r = splitTree p mempty xs++takeUntil :: (Measured v a) => (v -> Bool) -> FingerTree v a -> FingerTree v a+takeUntil p = fst . split p++dropUntil :: (Measured v a) => (v -> Bool) -> FingerTree v a -> FingerTree v a+dropUntil p = snd . split p++data Split t a = Split t a t++splitTree :: (Measured v a) =>+ (v -> Bool) -> v -> FingerTree v a -> Split (FingerTree v a) a+splitTree _ _ Empty = error "FingerTree.splitTree: bug!"+splitTree _p _i (Single x) = Split Empty x Empty+splitTree p i (Deep _ pr m sf)+ | p vpr = let Split l x r = splitDigit p i pr+ in Split (maybe Empty digitToTree l) x (deepL r m sf)+ | p vm = let Split ml xs mr = splitTree p vpr m+ Split l x r = splitNode p (vpr `mappendVal` ml) xs+ in Split (deepR pr ml l) x (deepL r mr sf)+ | otherwise = let Split l x r = splitDigit p vm sf+ in Split (deepR pr m l) x (maybe Empty digitToTree r)+ where vpr = i `mappend` measure pr+ vm = vpr `mappendVal` m++mappendVal :: (Measured v a) => v -> FingerTree v a -> v+mappendVal v Empty = v+mappendVal v t = v `mappend` measure t++deepL :: (Measured v a) =>+ Maybe (Digit a) -> FingerTree v (Node v a) -> Digit a -> FingerTree v a+deepL Nothing m sf = case lview m of+ Nothing -> digitToTree sf+ Just (a,m') -> deep (nodeToDigit a) m' sf+deepL (Just pr) m sf = deep pr m sf++deepR :: (Measured v a) =>+ Digit a -> FingerTree v (Node v a) -> Maybe (Digit a) -> FingerTree v a+deepR pr m Nothing = case rview m of+ Nothing -> digitToTree pr+ Just (a,m') -> deep pr m' (nodeToDigit a)+deepR pr m (Just sf) = deep pr m sf++splitNode :: (Measured v a) => (v -> Bool) -> v -> Node v a ->+ Split (Maybe (Digit a)) a+splitNode p i (Node2 _ a b)+ | p va = Split Nothing a (Just (One b))+ | otherwise = Split (Just (One a)) b Nothing+ where va = i `mappend` measure a+splitNode p i (Node3 _ a b c)+ | p va = Split Nothing a (Just (Two b c))+ | p vab = Split (Just (One a)) b (Just (One c))+ | otherwise = Split (Just (Two a b)) c Nothing+ where va = i `mappend` measure a+ vab = va `mappend` measure b++splitDigit :: (Measured v a) => (v -> Bool) -> v -> Digit a ->+ Split (Maybe (Digit a)) a+splitDigit p i (One a) = i `seq` Split Nothing a Nothing+splitDigit p i (Two a b)+ | p va = Split Nothing a (Just (One b))+ | otherwise = Split (Just (One a)) b Nothing+ where va = i `mappend` measure a+splitDigit p i (Three a b c)+ | p va = Split Nothing a (Just (Two b c))+ | p vab = Split (Just (One a)) b (Just (One c))+ | otherwise = Split (Just (Two a b)) c Nothing+ where va = i `mappend` measure a+ vab = va `mappend` measure b+splitDigit p i (Four a b c d)+ | p va = Split Nothing a (Just (Three b c d))+ | p vab = Split (Just (One a)) b (Just (Two c d))+ | p vabc = Split (Just (Two a b)) c (Just (One d))+ | otherwise = Split (Just (Three a b c)) d Nothing+ where va = i `mappend` measure a+ vab = va `mappend` measure b+ vabc = vab `mappend` measure c+++-- | /O(n)/. The reverse of a sequence.+reverse :: (Measured v a) => FingerTree v a -> FingerTree v a+reverse = reverseTree id++reverseTree :: (Measured v2 a2) => (a1 -> a2) -> FingerTree v1 a1 -> FingerTree v2 a2+reverseTree _ Empty = Empty+reverseTree f (Single x) = Single (f x)+reverseTree f (Deep _ pr m sf) =+ deep (reverseDigit f sf) (reverseTree (reverseNode f) m) (reverseDigit f pr)++reverseNode :: (Measured v2 a2) => (a1 -> a2) -> Node v1 a1 -> Node v2 a2+reverseNode f (Node2 _ a b) = node2 (f b) (f a)+reverseNode f (Node3 _ a b c) = node3 (f c) (f b) (f a)++reverseDigit :: (a -> b) -> Digit a -> Digit b+reverseDigit f (One a) = One (f a)+reverseDigit f (Two a b) = Two (f b) (f a)+reverseDigit f (Three a b c) = Three (f c) (f b) (f a)+reverseDigit f (Four a b c d) = Four (f d) (f c) (f b) (f a)++++instance (Arbitrary a) => Arbitrary (Digit a) where+ arbitrary = oneof + [ arbitrary >>= \x -> return (One x)+ , two arbitrary >>= \(x,y) -> return (Two x y)+ , three arbitrary >>= \(x,y,z) -> return (Three x y z)+ , four arbitrary >>= \(x,y,z,w) -> return (Four x y z w)+ ]++ coarbitrary p = case p of+ One x -> variant 0 . coarbitrary x+ Two x y -> variant 1 . coarbitrary x . coarbitrary y+ Three x y z -> variant 2 . coarbitrary x . coarbitrary y+ . coarbitrary z+ Four x y z w -> variant 3 . coarbitrary x . coarbitrary y+ . coarbitrary z . coarbitrary w+++instance (Measured v a, Arbitrary a) => Arbitrary (Node v a) where+ arbitrary = oneof+ [ two arbitrary >>= \(x,y) -> return (node2 x y)+ , three arbitrary >>= \(x,y,z) -> return (node3 x y z)+ ]++ coarbitrary p = case p of+ Node2 _ x y -> variant 0 . coarbitrary x . coarbitrary y+ Node3 _ x y z -> variant 1 . coarbitrary x . coarbitrary y . coarbitrary z+++instance (Measured v a, Arbitrary a) => Arbitrary (FingerTree v a) where+ arbitrary = oneof+ [ return Empty+ , arbitrary >>= return . Single+ , do + pf <- arbitrary+ m <- arbitrary+ sf <- arbitrary+ return (deep pf m sf)+ ]++ coarbitrary p = case p of+ Empty -> variant 0+ Single x -> variant 1 . coarbitrary x+ Deep _ sf m pf -> variant 2 . coarbitrary sf . coarbitrary m . coarbitrary pf
+ src/Data/Edison/Seq/BankersQueue.hs view
@@ -0,0 +1,419 @@+-- |+-- Module : Data.Edison.Seq.BankersQueue+-- 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)+--+-- This module implements Banker's Queues. It has the standard running+-- times from "Data.Edison.Seq" except for the following:+--+-- * rcons, size, inBounds @O( 1 )@+--+-- /References:/+--+-- * Chris Okasaki, /Purely Functional Data Structures/,+-- 1998, sections 6.3.2 and 8.4.1.+--+-- * Chris Okasaki, \"Simple and efficient purely functional+-- queues and deques\", /Journal of Function Programming/+-- 5(4):583-592, October 1995.++module Data.Edison.Seq.BankersQueue (+ -- * Sequence Type+ Seq, -- instance of Sequence, Functor, Monad, MonadPlus++ -- * Sequence operations+ empty,singleton,lcons,rcons,append,lview,lhead,ltail,rview,rhead,rtail,+ lheadM,ltailM,rheadM,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 Data.Edison.Prelude+import qualified Data.Edison.Seq as S ( Sequence(..) ) +import Data.Edison.Seq.Defaults+import qualified Data.Edison.Seq.ListSeq as L+import Data.Monoid+import Control.Monad+import Control.Monad.Identity+import Test.QuickCheck++-- signatures for exported functions+moduleName :: String+empty :: Seq a+singleton :: a -> Seq a+lcons :: a -> Seq a -> Seq a+rcons :: a -> Seq a -> Seq a+append :: Seq a -> Seq a -> Seq a+lview :: (Monad m) => Seq a -> m (a, Seq a)+lhead :: Seq a -> a+lheadM :: (Monad m) => Seq a -> m a+ltail :: Seq a -> Seq a+ltailM :: (Monad m) => Seq a -> m (Seq a)+rview :: (Monad m) => Seq a -> m (a, Seq a)+rhead :: Seq a -> a+rheadM :: (Monad m) => Seq a -> m a+rtail :: Seq a -> Seq a+rtailM :: (Monad m) => Seq a -> m (Seq a)+null :: Seq a -> Bool+size :: Seq a -> Int+concat :: Seq (Seq a) -> Seq a+reverse :: Seq a -> Seq a+reverseOnto :: Seq a -> Seq a -> Seq a+fromList :: [a] -> Seq a+toList :: Seq a -> [a]+map :: (a -> b) -> Seq a -> Seq b+concatMap :: (a -> Seq b) -> Seq a -> Seq b+fold :: (a -> b -> b) -> b -> Seq a -> b+fold' :: (a -> b -> b) -> b -> Seq a -> b+fold1 :: (a -> a -> a) -> Seq a -> a+fold1' :: (a -> a -> a) -> Seq a -> a+foldr :: (a -> b -> b) -> b -> Seq a -> b+foldl :: (b -> a -> b) -> b -> Seq a -> b+foldr1 :: (a -> a -> a) -> Seq a -> a+foldl1 :: (a -> a -> a) -> Seq a -> a+reducer :: (a -> a -> a) -> a -> Seq a -> a+reducel :: (a -> a -> a) -> a -> Seq a -> a+reduce1 :: (a -> a -> a) -> Seq a -> a+foldr' :: (a -> b -> b) -> b -> Seq a -> b+foldl' :: (b -> a -> b) -> b -> Seq a -> b+foldr1' :: (a -> a -> a) -> Seq a -> a+foldl1' :: (a -> a -> a) -> Seq a -> a+reducer' :: (a -> a -> a) -> a -> Seq a -> a+reducel' :: (a -> a -> a) -> a -> Seq a -> a+reduce1' :: (a -> a -> a) -> Seq a -> a+copy :: Int -> a -> Seq a+inBounds :: Int -> Seq a -> Bool+lookup :: Int -> Seq a -> a+lookupM :: (Monad m) => Int -> Seq a -> m a+lookupWithDefault :: a -> Int -> Seq a -> a+update :: Int -> a -> Seq a -> Seq a+adjust :: (a -> a) -> Int -> Seq a -> Seq a+mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b+foldrWithIndex :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex :: (b -> Int -> a -> b) -> b -> Seq a -> b+foldrWithIndex' :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex' :: (b -> Int -> a -> b) -> b -> Seq a -> b+take :: Int -> Seq a -> Seq a+drop :: Int -> Seq a -> Seq a+splitAt :: Int -> Seq a -> (Seq a, Seq a)+subseq :: Int -> Int -> Seq a -> Seq a+filter :: (a -> Bool) -> Seq a -> Seq a+partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+takeWhile :: (a -> Bool) -> Seq a -> Seq a+dropWhile :: (a -> Bool) -> Seq a -> Seq a+splitWhile :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+zip :: Seq a -> Seq b -> Seq (a,b)+zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c)+zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c+zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d+unzip :: Seq (a,b) -> (Seq a, Seq b)+unzip3 :: Seq (a,b,c) -> (Seq a, Seq b, Seq c)+unzipWith :: (a -> b) -> (a -> c) -> Seq a -> (Seq b, Seq c)+unzipWith3 :: (a -> b) -> (a -> c) -> (a -> d) -> Seq a -> (Seq b, Seq c, Seq d)+strict :: Seq a -> Seq a+strictWith :: (a -> b) -> Seq a -> Seq a++structuralInvariant :: Seq a -> Bool++moduleName = "Data.Edison.Seq.BankersQueue"+++data Seq a = Q !Int [a] [a] !Int++-- invariant: front at least as long as rear+structuralInvariant (Q x f r y) =+ length f == x && length r == y && x >= y+++-- not exported+makeQ :: Int -> [a] -> [a] -> Int -> Seq a+makeQ i xs ys j+ | j > i = Q (i + j) (xs ++ L.reverse ys) [] 0+ | otherwise = Q i xs ys j++empty = Q 0 [] [] 0+singleton x = Q 1 [x] [] 0+lcons x (Q i xs ys j) = Q (i+1) (x:xs) ys j+rcons y (Q i xs ys j) = makeQ i xs (y:ys) (j+1)++append (Q i1 xs1 ys1 j1) (Q i2 xs2 ys2 j2) =+ Q (i1 + j1 + i2) (xs1 ++ L.reverseOnto ys1 xs2) ys2 j2++lview (Q _ [] _ _) = fail "BankersQueue.lview: empty sequence"+lview (Q i (x:xs) ys j) = return (x, makeQ (i-1) xs ys j)++lhead (Q _ [] _ _) = error "BankersQueue.lhead: empty sequence"+lhead (Q _ (x:xs) _ _) = x++lheadM (Q _ [] _ _) = fail "BankersQueue.lheadM: empty sequence"+lheadM (Q _ (x:xs) _ _) = return x++ltail (Q i (x:xs) ys j) = makeQ (i-1) xs ys j+ltail q = error "BankersQueue.ltail: empty sequence"++ltailM (Q i (x:xs) ys j) = return (makeQ (i-1) xs ys j)+ltailM q = fail "BankersQueue.ltail: empty sequence"++rview (Q i xs (y:ys) j) = return (y, Q i xs ys (j-1))+rview (Q i xs [] _) =+ case L.rview xs of+ Nothing -> fail "BankersQueue.rview: empty sequence"+ Just (x,xs') -> return (x, Q (i-1) xs' [] 0)++rhead (Q i xs (y:ys) j) = y+rhead (Q _ [] [] _) = error "BankersQueue.rhead: empty sequence"+rhead (Q i xs [] _) = L.rhead xs++rheadM (Q i xs (y:ys) j) = return y+rheadM (Q _ [] [] _) = fail "BankersQueue.rheadM: empty sequence"+rheadM (Q i xs [] _) = return (L.rhead xs)++rtail (Q i xs (y:ys) j) = Q i xs ys (j-1)+rtail q@(Q _ [] [] _) = error "BankersQueue.rtail: empty sequence"+rtail (Q i xs [] _) = Q (i-1) (L.rtail xs) [] 0++rtailM (Q i xs (y:ys) j) = return (Q i xs ys (j-1))+rtailM q@(Q _ [] [] _) = fail "BankersQueue.rtailM: empty sequence"+rtailM (Q i xs [] _) = return (Q (i-1) (L.rtail xs) [] 0)++null (Q i _ _ _) = (i == 0)+size (Q i xs ys j) = i + j+reverse (Q i xs ys j) = makeQ j ys xs i++reverseOnto (Q i1 xs1 ys1 j1) (Q i2 xs2 ys2 j2) =+ Q (i1 + j1 + i2) (ys1 ++ L.reverseOnto xs1 xs2) ys2 j2++fromList xs = Q (length xs) xs [] 0++toList (Q i xs ys j)+ | j == 0 = xs+ | otherwise = xs ++ L.reverse ys++map f (Q i xs ys j) = Q i (L.map f xs) (L.map f ys) j++-- local fn on lists+revfoldr f e [] = e+revfoldr f e (x:xs) = revfoldr f (f x e) xs++revfoldr' f e [] = e+revfoldr' f e (x:xs) = e `seq` revfoldr' f (f x e) xs++-- local fn on lists+revfoldl f e [] = e+revfoldl f e (x:xs) = f (revfoldl f e xs) x++revfoldl' f e [] = e+revfoldl' f e (x:xs) = (\z -> f z x) $! (revfoldl f e xs)++fold f e (Q i xs ys j) = L.foldr f (L.foldr f e ys) xs+fold' f e (Q i xs ys j) = (L.foldl' (flip f) $! (L.foldl' (flip f) e ys)) xs+fold1 = fold1UsingFold+fold1' = fold1'UsingFold'++foldr f e (Q i xs ys j) = L.foldr f (revfoldr f e ys) xs+foldr' f e (Q i xs ys j) = L.foldr' f (revfoldr' f e ys) xs+foldl f e (Q i xs ys j) = revfoldl f (L.foldl f e xs) ys+foldl' f e (Q i xs ys j) = revfoldl' f (L.foldl' f e xs) ys++foldr1 f (Q i xs (y:ys) j) = L.foldr f (revfoldr f y ys) xs+foldr1 f (Q i xs [] _)+ | i == 0 = error "BankersQueue.foldr1: empty sequence"+ | otherwise = L.foldr1 f xs++foldr1' f (Q i xs (y:ys) j) = L.foldr' f (revfoldr' f y ys) xs+foldr1' f (Q i xs [] _)+ | i == 0 = error "BankersQueue.foldr1': empty sequence"+ | otherwise = L.foldr1' f xs++foldl1 f (Q i (x:xs) ys j) = revfoldl f (L.foldl f x xs) ys+foldl1 f _ = error "BankersQueue.foldl1: empty sequence"++foldl1' f (Q i (x:xs) ys j) = revfoldl' f (L.foldl' f x xs) ys+foldl1' f _ = error "BankersQueue.foldl1': empty sequence"++copy n x + | n < 0 = empty+ | otherwise = Q n (L.copy n x) [] 0++-- reduce1: given sizes could do more effective job of dividing evenly!++lookup idx q = runIdentity (lookupM idx q)++lookupM idx (Q i xs ys j)+ | idx < i = L.lookupM idx xs+ | otherwise = L.lookupM (j - (idx - i) - 1) ys++lookupWithDefault d idx (Q i xs ys j)+ | idx < i = L.lookupWithDefault d idx xs+ | otherwise = L.lookupWithDefault d (j - (idx - i) - 1) ys++update idx e q@(Q i xs ys j)+ | idx < i = if idx < 0 then q+ else Q i (L.update idx e xs) ys j+ | otherwise = let k' = j - (idx - i) - 1+ in if k' < 0 then q+ else Q i xs (L.update k' e ys) j++adjust f idx q@(Q i xs ys j)+ | idx < i = if idx < 0 then q+ else Q i (L.adjust f idx xs) ys j+ | otherwise = let k' = j - (idx - i) - 1+ in if k' < 0 then q+ else Q i xs (L.adjust f k' ys) j++{- +could do+ mapWithIndex :: (Int -> a -> b) -> s a -> s b+ foldrWithIndex :: (Int -> a -> b -> b) -> b -> s a -> b+ foldlWithIndex :: (b -> Int -> a -> b) -> b -> s a -> b+but don't bother for now+-}++take len q@(Q i xs ys j) =+ if len <= i then+ if len <= 0 then empty+ else Q len (L.take len xs) [] 0+ else let len' = len - i in+ if len' >= j then q+ else Q i xs (L.drop (j - len') ys) len'++drop len q@(Q i xs ys j) =+ if len <= i then+ if len <= 0 then q+ else makeQ (i - len) (L.drop len xs) ys j+ else let len' = len - i in+ if len' >= j then empty+ else Q (j - len') (L.reverse (L.take (j - len') ys)) [] 0+ -- could write more efficient version of reverse (take ...) ++splitAt idx q@(Q i xs ys j) =+ if idx <= i then+ if idx <= 0 then (empty, q)+ else let (xs',xs'') = L.splitAt idx xs+ in (Q idx xs' [] 0, makeQ (i - idx) xs'' ys j)+ else let idx' = idx - i in+ if idx' >= j then (q, empty)+ else let (ys', ys'') = L.splitAt (j - idx') ys+ in (Q i xs ys'' idx', Q (j - idx') (L.reverse ys') [] 0)+ -- could do splitAt followed by reverse more efficiently...+ ++strict l@(Q i xs ys j) = L.strict xs `seq` L.strict ys `seq` l+strictWith f l@(Q i xs ys j) = L.strictWith f xs `seq` L.strictWith f ys `seq` l++-- the remaining functions all use defaults++concat = concatUsingFoldr+concatMap = concatMapUsingFoldr+reducer = reducerUsingReduce1+reducel = reducelUsingReduce1+reduce1 = reduce1UsingLists+reducer' = reducer'UsingReduce1'+reducel' = reducel'UsingReduce1'+reduce1' = reduce1'UsingLists+inBounds = inBoundsUsingSize+mapWithIndex = mapWithIndexUsingLists+foldrWithIndex = foldrWithIndexUsingLists+foldrWithIndex' = foldrWithIndex'UsingLists+foldlWithIndex = foldlWithIndexUsingLists+foldlWithIndex' = foldlWithIndex'UsingLists+subseq = subseqDefault+filter = filterUsingLists+partition = partitionUsingLists+takeWhile = takeWhileUsingLview+dropWhile = dropWhileUsingLview+splitWhile = splitWhileUsingLview+zip = zipUsingLists+zip3 = zip3UsingLists+zipWith = zipWithUsingLists+zipWith3 = zipWith3UsingLists+unzip = unzipUsingLists+unzip3 = unzip3UsingLists+unzipWith = unzipWithUsingLists+unzipWith3 = unzipWith3UsingLists++-- instances++instance S.Sequence Seq where+ {lcons = lcons; rcons = rcons;+ lview = lview; lhead = lhead; ltail = ltail;+ lheadM = lheadM; ltailM = ltailM; rheadM = rheadM; rtailM = rtailM;+ rview = rview; rhead = rhead; rtail = rtail; null = null;+ 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; reducer' = reducer';+ reducel = reducel; reducel' = reducel'; reduce1 = reduce1; reduce1' = reduce1';+ copy = copy; inBounds = inBounds; lookup = lookup;+ lookupM = lookupM; lookupWithDefault = lookupWithDefault;+ update = update; adjust = adjust; mapWithIndex = mapWithIndex;+ foldrWithIndex = foldrWithIndex; foldlWithIndex = foldlWithIndex;+ foldrWithIndex' = foldrWithIndex'; 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}++instance Functor Seq where+ fmap = map++instance Monad Seq where+ return = singleton+ xs >>= k = concatMap k xs++instance MonadPlus Seq where+ mplus = append+ mzero = empty++instance Eq a => Eq (Seq a) where+ q1 == q2 =+ (size q1 == size q2) && (toList q1 == toList q2)++instance Ord a => Ord (Seq a) where+ compare = defaultCompare++instance Show a => Show (Seq a) where+ showsPrec = showsPrecUsingToList++instance Read a => Read (Seq a) where+ readsPrec = readsPrecUsingFromList++instance Arbitrary a => Arbitrary (Seq a) where+ arbitrary =+ do xs <- arbitrary+ ys <- arbitrary+ return (let i = L.size xs+ j = L.size ys+ in if i >= j then Q i xs ys j else Q j ys xs i)++ coarbitrary (Q i xs ys j) = coarbitrary xs . coarbitrary ys++instance Monoid (Seq a) where+ mempty = empty+ mappend = append
+ src/Data/Edison/Seq/BinaryRandList.hs view
@@ -0,0 +1,447 @@+-- |+-- Module : Data.Edison.Seq.BinaryRandList+-- 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)+--+-- Binary Random-Access lists. All functions have the standard running+-- times from "Data.Edison.Seq" except the following:+--+-- * lcons, lhead, ltail*, lview*, rhead*, size, lookup*, update, adjust, drop @O( log n )@+--+-- * copy, inBounds @O( i )@+--+-- * append, reverseOnto @O( n1 + log n2 )@+--+-- * take, splitAt @O( i + log n )@+--+-- * subseq @O( log n + len )@+--+-- * zip @O( min( n1, n2 ) + log max( n1, n2 ) )@+--+-- /References:/+--+-- * Chris Okasaki. /Purely Functional Data Structures/. 1998.+-- Section 10.1.2.++module Data.Edison.Seq.BinaryRandList (+ -- * Sequence Type+ Seq, -- instance of Sequence, Functor, Monad, MonadPlus++ -- * Sequence Operations+ empty,singleton,lcons,rcons,append,lview,lhead,ltail,rview,rhead,rtail,+ lheadM,ltailM,rheadM,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 Control.Monad.Identity+import Data.Maybe++import Data.Edison.Prelude+import qualified Data.Edison.Seq as S ( Sequence(..) ) +import Data.Edison.Seq.Defaults+import Data.Monoid+import Control.Monad+import Test.QuickCheck++-- signatures for exported functions+moduleName :: String+empty :: Seq a+singleton :: a -> Seq a+lcons :: a -> Seq a -> Seq a+rcons :: a -> Seq a -> Seq a+append :: Seq a -> Seq a -> Seq a+lview :: (Monad m) => Seq a -> m (a, Seq a)+lhead :: Seq a -> a+lheadM :: (Monad m) => Seq a -> m a+ltail :: Seq a -> Seq a+ltailM :: (Monad m) => Seq a -> m (Seq a)+rview :: (Monad m) => Seq a -> m (a, Seq a)+rhead :: Seq a -> a+rheadM :: (Monad m) => Seq a -> m a+rtail :: Seq a -> Seq a+rtailM :: (Monad m) => Seq a -> m (Seq a)+null :: Seq a -> Bool+size :: Seq a -> Int+concat :: Seq (Seq a) -> Seq a+reverse :: Seq a -> Seq a+reverseOnto :: Seq a -> Seq a -> Seq a+fromList :: [a] -> Seq a+toList :: Seq a -> [a]+map :: (a -> b) -> Seq a -> Seq b+concatMap :: (a -> Seq b) -> Seq a -> Seq b+fold :: (a -> b -> b) -> b -> Seq a -> b+fold' :: (a -> b -> b) -> b -> Seq a -> b+fold1 :: (a -> a -> a) -> Seq a -> a+fold1' :: (a -> a -> a) -> Seq a -> a+foldr :: (a -> b -> b) -> b -> Seq a -> b+foldl :: (b -> a -> b) -> b -> Seq a -> b+foldr1 :: (a -> a -> a) -> Seq a -> a+foldl1 :: (a -> a -> a) -> Seq a -> a+reducer :: (a -> a -> a) -> a -> Seq a -> a+reducel :: (a -> a -> a) -> a -> Seq a -> a+reduce1 :: (a -> a -> a) -> Seq a -> a+foldr' :: (a -> b -> b) -> b -> Seq a -> b+foldl' :: (b -> a -> b) -> b -> Seq a -> b+foldr1' :: (a -> a -> a) -> Seq a -> a+foldl1' :: (a -> a -> a) -> Seq a -> a+reducer' :: (a -> a -> a) -> a -> Seq a -> a+reducel' :: (a -> a -> a) -> a -> Seq a -> a+reduce1' :: (a -> a -> a) -> Seq a -> a+copy :: Int -> a -> Seq a+inBounds :: Int -> Seq a -> Bool+lookup :: Int -> Seq a -> a+lookupM :: (Monad m) => Int -> Seq a -> m a+lookupWithDefault :: a -> Int -> Seq a -> a+update :: Int -> a -> Seq a -> Seq a+adjust :: (a -> a) -> Int -> Seq a -> Seq a+mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b+foldrWithIndex :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex :: (b -> Int -> a -> b) -> b -> Seq a -> b+foldrWithIndex' :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex' :: (b -> Int -> a -> b) -> b -> Seq a -> b+take :: Int -> Seq a -> Seq a+drop :: Int -> Seq a -> Seq a+splitAt :: Int -> Seq a -> (Seq a, Seq a)+subseq :: Int -> Int -> Seq a -> Seq a+filter :: (a -> Bool) -> Seq a -> Seq a+partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+takeWhile :: (a -> Bool) -> Seq a -> Seq a+dropWhile :: (a -> Bool) -> Seq a -> Seq a+splitWhile :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+zip :: Seq a -> Seq b -> Seq (a,b)+zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c)+zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c+zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d+unzip :: Seq (a,b) -> (Seq a, Seq b)+unzip3 :: Seq (a,b,c) -> (Seq a, Seq b, Seq c)+unzipWith :: (a -> b) -> (a -> c) -> Seq a -> (Seq b, Seq c)+unzipWith3 :: (a -> b) -> (a -> c) -> (a -> d) -> Seq a -> (Seq b, Seq c, Seq d)+strict :: Seq a -> Seq a+strictWith :: (a -> b) -> Seq a -> Seq a+structuralInvariant :: Seq a -> Bool++moduleName = "Data.Edison.Seq.BinaryRandList"+++data Seq a = E | Even (Seq (a,a)) | Odd a (Seq (a,a)) deriving (Eq)++-- not exported, rewrite as bit ops?+--even n = (n `mod` 2) == 0+--odd n = (n `mod` 2) <> 0+half n = n `div` 2++mkEven E = E+mkEven ps = Even ps++empty = E+singleton x = Odd x E++lcons x E = Odd x E+lcons x (Even ps) = Odd x ps+lcons x (Odd y ps) = Even (lcons (x,y) ps)++append xs E = xs+append xs ys@(Even pys) =+ case xs of+ E -> ys+ Even pxs -> Even (append pxs pys)+ Odd x pxs -> Odd x (append pxs pys)+append xs ys@(Odd _ _) = foldr lcons ys xs++copy n x + | n <= 0 = E+ | otherwise = cp n x+ where cp :: Int -> a -> Seq a+ cp n x+ | odd n = Odd x (cp (half n) (x,x))+ | n == 0 = E+ | otherwise = Even (cp (half n) (x,x))++lview E = fail "BinaryRandList.lview: empty sequence"+lview (Even ps) = case lview ps of+ Just ((x,y), ps') -> return (x, Odd y ps')+ Nothing -> error "BinaryRandList.lview: bug!"+lview (Odd x ps) = return (x, mkEven ps)++lhead E = error "BinaryRandList.lhead: empty sequence"+lhead (Even ps) = fst (lhead ps)+lhead (Odd x ps) = x++lheadM E = fail "BinaryRandList.lheadM: empty sequence"+lheadM (Even ps) = return (fst (lhead ps))+lheadM (Odd x ps) = return (x)++ltail E = error "BinaryRandList.ltail: empty sequence"+ltail (Even ps) = case lview ps of+ Just ((x,y), ps') -> Odd y ps'+ Nothing -> error "BinaryRandList.ltail: bug!"+ltail (Odd x ps) = mkEven ps++ltailM E = fail "BinaryRandList.ltailM: empty sequence"+ltailM (Even ps) = case lview ps of+ Just ((x,y), ps') -> return (Odd y ps')+ Nothing -> error "BinaryRandList.ltailM: bug!"+ltailM (Odd x ps) = return (mkEven ps)++rhead E = error "BinaryRandList.rhead: empty sequence"+rhead (Even ps) = snd (rhead ps)+rhead (Odd x E) = x+rhead (Odd x ps) = snd (rhead ps)++rheadM E = fail "BinaryRandList.rheadM: empty sequence"+rheadM (Even ps) = return (snd (rhead ps))+rheadM (Odd x E) = return x+rheadM (Odd x ps) = return (snd (rhead ps))+++null E = True+null _ = False++size E = 0+size (Even ps) = 2 * size ps+size (Odd x ps) = 1 + 2 * size ps++map f E = E+map f (Even ps) = Even (map (\(x,y) -> (f x,f y)) ps)+map f (Odd x ps) = Odd (f x) (map (\(x,y) -> (f x,f y)) ps)++fold = foldr+fold' = foldr'+fold1 = fold1UsingFold+fold1' = fold1'UsingFold'++foldr f e E = e+foldr f e (Even ps) = foldr (\(x,y) e -> f x (f y e)) e ps+foldr f e (Odd x ps) = f x (foldr (\(x,y) e -> f x (f y e)) e ps)++foldr' f e E = e+foldr' f e (Even ps) = foldr' (\(x,y) e -> f x $! f y $! e) e ps+foldr' f e (Odd x ps) = f x $! (foldr' (\(x,y) e -> f x $! f y $! e) e ps)++foldl f e E = e+foldl f e (Even ps) = foldl (\e (x,y) -> f (f e x) y) e ps+foldl f e (Odd x ps) = foldl (\e (x,y) -> f (f e x) y) (f e x) ps++foldl' f e E = e+foldl' f e (Even ps) = foldl' (\e (x,y) -> f (f e x) y) e ps+foldl' f e (Odd x ps) = e `seq` foldl' (\e (x,y) -> e `seq` (\z -> f z y) $! (f e x)) (f e x) ps++reduce1 f E = error "BinaryRandList.reduce1: empty seq"+reduce1 f (Even ps) = reduce1 f (map (uncurry f) ps)+reduce1 f (Odd x E) = x+reduce1 f (Odd x ps) = f x (reduce1 f (map (uncurry f) ps))++reduce1' f E = error "BinaryRandList.reduce1': empty seq"+reduce1' f (Even ps) = reduce1' f (map (uncurry f) ps)+reduce1' f (Odd x E) = x+reduce1' f (Odd x ps) = (f $! x) $! (reduce1' f (map (uncurry f) ps))+++inBounds i xs = (i >= 0) && inb xs i+ where inb :: Seq a -> Int -> Bool+ inb E i = False+ inb (Even ps) i = inb ps (half i)+ inb (Odd x ps) i = (i == 0) || inb ps (half (i-1))++lookup i xs = runIdentity (lookupM i xs)++lookupM i xs+ | i < 0 = fail "BinaryRandList.lookup: bad subscript"+ | otherwise = lookFun nothing xs i return+ where+ nothing = fail "BinaryRandList.lookup: not found"++lookupWithDefault d i xs+ | i < 0 = d+ | otherwise = lookFun d xs i id++-- not exported+lookFun :: b -> Seq a -> Int -> (a -> b) -> b+lookFun d E i f = d+lookFun d (Even ps) i f+ | even i = lookFun d ps (half i) (f . fst)+ | otherwise = lookFun d ps (half i) (f . snd)+lookFun d (Odd x ps) i f+ | odd i = lookFun d ps (half (i-1)) (f . fst)+ | i == 0 = f x+ | otherwise = lookFun d ps (half (i-1)) (f . snd)++adjust f i xs+ | i < 0 = xs+ | otherwise = adj f i xs+ where adj :: (a -> a) -> Int -> Seq a -> Seq a+ adj f i E = E+ adj f i (Even ps)+ | even i = Even (adj (mapFst f) (half i) ps)+ | otherwise = Even (adj (mapSnd f) (half i) ps)+ adj f i (Odd x ps)+ | odd i = Odd x (adj (mapFst f) (half (i-1)) ps)+ | i == 0 = Odd (f x) ps+ | otherwise = Odd x (adj (mapSnd f) (half (i-1)) ps)++-- not exported+mapFst f (x,y) = (f x,y)+mapSnd f (x,y) = (x,f y)++take n xs = if n <= 0 then E else tak n xs+ where tak :: Int -> Seq a -> Seq a+ tak 0 xs = E+ tak i E = E+ tak i (Even ps)+ | even i = Even (tak (half i) ps)+ tak i (Odd x ps)+ | odd i = Odd x (tak (half (i-1)) ps)+ tak i xs = takeUsingLists i xs++-- drop is O(log^2 n) instead of O(log n)??+drop n xs = if n <= 0 then xs else drp n xs+ where drp :: Int -> Seq a -> Seq a+ drp 0 xs = xs+ drp i E = E+ drp i (Even ps)+ | even i = mkEven (drp (half i) ps)+ | otherwise = fromMaybe empty (ltailM (mkEven (drp (half i) ps)))+ drp i (Odd _ ps)+ | odd i = mkEven (drp (half (i-1)) ps)+ | otherwise = fromMaybe empty (ltailM (mkEven (drp (half (i-1)) ps)))+++strict l@E = l+strict l@(Even l') = strict l' `seq` l+strict l@(Odd x l') = strict l' `seq` l++strictWith f l@E = l+strictWith f l@(Even l') = strictWith (\ (x,y) -> f x `seq` f y) l' `seq` l+strictWith f l@(Odd x l') = f x `seq` strictWith (\ (x,y) -> f x `seq` f y) `seq` l+++-- structural invariants are enforced by the type system+structuralInvariant = const True++-- the remaining functions all use defaults++rcons = rconsUsingFoldr+rview = rviewDefault+rtail = rtailUsingLview+rtailM = rtailMUsingLview+concat = concatUsingFoldr+reverse = reverseUsingReverseOnto+reverseOnto = reverseOntoUsingFoldl+fromList = fromListUsingCons+toList = toListUsingFoldr+concatMap = concatMapUsingFoldr+foldr1 = foldr1UsingLview+foldr1' = foldr1'UsingLview+foldl1 = foldl1UsingFoldl+foldl1' = foldl1'UsingFoldl'+reducer = reducerUsingReduce1+reducel = reducelUsingReduce1+reducer' = reducer'UsingReduce1'+reducel' = reducel'UsingReduce1'+update = updateUsingAdjust+mapWithIndex = mapWithIndexUsingLists+foldrWithIndex = foldrWithIndexUsingLists+foldlWithIndex = foldlWithIndexUsingLists+foldrWithIndex' = foldrWithIndex'UsingLists+foldlWithIndex' = foldlWithIndex'UsingLists+splitAt = splitAtDefault+filter = filterUsingFoldr+partition = partitionUsingFoldr+subseq = subseqDefault+takeWhile = takeWhileUsingLview+dropWhile = dropWhileUsingLview+splitWhile = splitWhileUsingLview++-- for zips, could optimize by calculating which one is shorter and+-- retaining its shape++zip = zipUsingLists+zip3 = zip3UsingLists+zipWith = zipWithUsingLists+zipWith3 = zipWith3UsingLists+unzip = unzipUsingLists+unzip3 = unzip3UsingLists+unzipWith = unzipWithUsingLists+unzipWith3 = unzipWith3UsingLists++-- instances++instance S.Sequence Seq where+ {lcons = lcons; rcons = rcons;+ lview = lview; lhead = lhead; ltail = ltail;+ lheadM = lheadM; ltailM = ltailM; rheadM = rheadM; rtailM = rtailM;+ rview = rview; rhead = rhead; rtail = rtail; null = null;+ 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; reducer' = reducer'; reducel = reducel;+ reducel' = reducel'; reduce1 = reduce1; 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}++instance Functor Seq where+ fmap = map++instance Monad Seq where+ return = singleton+ xs >>= k = concatMap k xs++instance MonadPlus Seq where+ mplus = append+ mzero = empty++-- instance Eq (Seq a) is derived++instance Ord a => Ord (Seq a) where+ compare = defaultCompare++instance Show a => Show (Seq a) where+ showsPrec = showsPrecUsingToList++instance Read a => Read (Seq a) where+ readsPrec = readsPrecUsingFromList++instance Arbitrary a => Arbitrary (Seq a) where+ arbitrary = do xs <- arbitrary + return (fromList xs)++ coarbitrary E = variant 0+ coarbitrary (Even ps) = variant 1 . coarbitrary ps+ coarbitrary (Odd x ps) = variant 2 . coarbitrary x . coarbitrary ps++instance Monoid (Seq a) where+ mempty = empty+ mappend = append
+ src/Data/Edison/Seq/BraunSeq.hs view
@@ -0,0 +1,548 @@+-- |+-- Module : Data.Edison.Seq.BraunSeq+-- 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)+--+-- One-sided Braun sequences. All running times are as listed in +-- "Data.Edison.Seq" except the following:+--+-- * lview, lcons, ltail* @O( log n )@+--+-- * rcons, rview, rhead*, rtail*, size @O( log^2 n )@+--+-- * copy, inBounds, lookup*, update, adjust @O( log i )@+--+-- * append @O( n1 log n2 )@+--+-- * concat @O( n + m log m )@+--+-- * drop, splitAt @O( i log n )@+--+-- * subseq @O( i log n + len )@+--+-- * reverseOnto @O( n1 log n2 )@+--+-- * concatMap, (>>=) @O( n * t + m log 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@+--+-- By keeping track of the size, we could get rcons, rview, rhead*, and rtail*+-- down to @O(log n)@ as well; furthermore, size would be @O( 1 )@.+--+-- /References:/+--+-- * Rob Hoogerwoord. \"A symmetric set of efficient list operations\".+-- /Journal of Functional Programming/, 2(4):505--513, 1992.+--+-- * Rob Hoogerwoord. \"A Logarithmic Implementation of Flexible Arrays\".+-- /Mathematics of Program Construction/ (MPC'92), pages 191-207.+--+-- * Chris Okasaki. \"Three algorithms on Braun Trees\". +-- /Journal of Function Programming/ 7(6):661-666. Novemebr 1997.++module Data.Edison.Seq.BraunSeq (+ -- * Sequence Type+ Seq, -- instance of Sequence, Functor, Monad, MonadPlus++ -- * Sequence Operations+ empty,singleton,lcons,rcons,append,lview,lhead,ltail,rview,rhead,rtail,+ lheadM,ltailM,rheadM,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 Control.Monad+import Control.Monad.Identity+import Data.Maybe+import Data.Monoid+import Test.QuickCheck++import Data.Edison.Prelude+import qualified Data.Edison.Seq as S ( Sequence(..) )+import Data.Edison.Seq.Defaults+import qualified Data.Edison.Seq.ListSeq as L+++-- signatures for exported functions+moduleName :: String+empty :: Seq a+singleton :: a -> Seq a+lcons :: a -> Seq a -> Seq a+rcons :: a -> Seq a -> Seq a+append :: Seq a -> Seq a -> Seq a+lview :: (Monad m) => Seq a -> m (a, Seq a)+lhead :: Seq a -> a+lheadM :: (Monad m) => Seq a -> m a+ltail :: Seq a -> Seq a+ltailM :: (Monad m) => Seq a -> m (Seq a)+rview :: (Monad m) => Seq a -> m (a, Seq a)+rhead :: Seq a -> a+rheadM :: (Monad m) => Seq a -> m a+rtail :: Seq a -> Seq a+rtailM :: (Monad m) => Seq a -> m (Seq a)+null :: Seq a -> Bool+size :: Seq a -> Int+concat :: Seq (Seq a) -> Seq a+reverse :: Seq a -> Seq a+reverseOnto :: Seq a -> Seq a -> Seq a+fromList :: [a] -> Seq a+toList :: Seq a -> [a]+map :: (a -> b) -> Seq a -> Seq b+concatMap :: (a -> Seq b) -> Seq a -> Seq b+fold :: (a -> b -> b) -> b -> Seq a -> b+fold' :: (a -> b -> b) -> b -> Seq a -> b+fold1 :: (a -> a -> a) -> Seq a -> a+fold1' :: (a -> a -> a) -> Seq a -> a+foldr :: (a -> b -> b) -> b -> Seq a -> b+foldl :: (b -> a -> b) -> b -> Seq a -> b+foldr1 :: (a -> a -> a) -> Seq a -> a+foldl1 :: (a -> a -> a) -> Seq a -> a+reducer :: (a -> a -> a) -> a -> Seq a -> a+reducel :: (a -> a -> a) -> a -> Seq a -> a+reduce1 :: (a -> a -> a) -> Seq a -> a+foldr' :: (a -> b -> b) -> b -> Seq a -> b+foldl' :: (b -> a -> b) -> b -> Seq a -> b+foldr1' :: (a -> a -> a) -> Seq a -> a+foldl1' :: (a -> a -> a) -> Seq a -> a+reducer' :: (a -> a -> a) -> a -> Seq a -> a+reducel' :: (a -> a -> a) -> a -> Seq a -> a+reduce1' :: (a -> a -> a) -> Seq a -> a+copy :: Int -> a -> Seq a+inBounds :: Int -> Seq a -> Bool+lookup :: Int -> Seq a -> a+lookupM :: (Monad m) => Int -> Seq a -> m a+lookupWithDefault :: a -> Int -> Seq a -> a+update :: Int -> a -> Seq a -> Seq a+adjust :: (a -> a) -> Int -> Seq a -> Seq a+mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b+foldrWithIndex :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex :: (b -> Int -> a -> b) -> b -> Seq a -> b+foldrWithIndex' :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex' :: (b -> Int -> a -> b) -> b -> Seq a -> b+take :: Int -> Seq a -> Seq a+drop :: Int -> Seq a -> Seq a+splitAt :: Int -> Seq a -> (Seq a, Seq a)+subseq :: Int -> Int -> Seq a -> Seq a+filter :: (a -> Bool) -> Seq a -> Seq a+partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+takeWhile :: (a -> Bool) -> Seq a -> Seq a+dropWhile :: (a -> Bool) -> Seq a -> Seq a+splitWhile :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+zip :: Seq a -> Seq b -> Seq (a,b)+zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c)+zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c+zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d+unzip :: Seq (a,b) -> (Seq a, Seq b)+unzip3 :: Seq (a,b,c) -> (Seq a, Seq b, Seq c)+unzipWith :: (a -> b) -> (a -> c) -> Seq a -> (Seq b, Seq c)+unzipWith3 :: (a -> b) -> (a -> c) -> (a -> d) -> Seq a -> (Seq b, Seq c, Seq d)+strict :: Seq a -> Seq a+strictWith :: (a -> b) -> Seq a -> Seq a+structuralInvariant :: Seq a -> Bool++moduleName = "Data.Edison.Seq.BraunSeq"+++data Seq a = E | B a (Seq a) (Seq a) deriving (Eq)++half :: Int -> Int+half n = n `quot` 2 -- use a shift?++empty = E+singleton x = B x E E++lcons x E = singleton x+lcons x (B y a b) = B x (lcons y b) a++rcons y ys = insAt (size ys) ys+ where insAt 0 _ = singleton y+ insAt i (B x a b)+ | odd i = B x (insAt (half i) a) b+ | otherwise = B x a (insAt (half i - 1) b)+ insAt _ _ = error "BraunSeq.rcons: bug. Impossible case!"++append xs E = xs+append xs ys = app (size xs) xs ys+ where app 0 xs ys = ys+ app n xs E = xs+ app n (B x a b) (B y c d)+ | odd n = B x (app m a (lcons y d)) (app m b c)+ | otherwise = B x (app m a c) (app (m-1) b (lcons y d))+ where m = half n+ app _ _ _ = error "BraunSeq.append: bug!"+ -- how does it compare to converting to/from lists?++lview E = fail "BraunSeq.lview: empty sequence"+lview (B x a b) = return (x, combine a b)++-- not exported+combine E _ = E+combine (B x a b) c = B x c (combine a b)++lhead E = error "BraunSeq.lhead: empty sequence"+lhead (B x a b) = x++lheadM E = fail "BraunSeq.lheadM: empty sequence"+lheadM (B x a b) = return x++ltail E = error "BraunSeq.ltail: empty sequence"+ltail (B x a b) = combine a b++ltailM E = fail "BraunSeq.ltailM: empty sequence"+ltailM (B x a b) = return (combine a b)++-- not exported+-- precondition: i >= 0+delAt 0 _ = E+delAt i (B x a b)+ | odd i = B x (delAt (half i) a) b+ | otherwise = B x a (delAt (half i - 1) b)+delAt _ _ = error "BraunSeq.delAt: bug. Impossible case!"++rview E = fail "BraunSeq.rview: empty sequence"+rview xs = return (lookup m xs, delAt m xs)+ where m = size xs - 1++rhead E = error "BraunSeq.rhead: empty sequence"+rhead xs = lookup (size xs - 1) xs++rheadM E = fail "BraunSeq.rheadM: empty sequence"+rheadM xs = return (lookup (size xs - 1) xs)++rtail E = error "BraunSeq.rtail: empty sequence"+rtail xs = delAt (size xs - 1) xs++rtailM E = fail "BraunSeq.rtailM: empty sequence"+rtailM xs = return (delAt (size xs - 1) xs)++null E = True+null _ = False++size E = 0+size (B x a b) = 1 + n + n + diff n a+ where n = size b++ diff 0 E = 0+ diff 0 (B x a b) = 1+ diff i (B x a b)+ | odd i = diff (half i) a+ | otherwise = diff (half i - 1) b+ diff _ _ = error "BraunSeq.size: bug. Impossible case in diff!"++reverse xs = rev00 (size xs) xs+ where+ rev00 n xs+ | n <= 1 = xs+ rev00 n (B x a b)+ | odd n = let a' = rev00 m a+ (x',b') = rev11 m x b in B x' a' b'+ | otherwise = let (x',a') = rev01 m a+ b' = rev10 (m-1) x b in B x' b' a'+ where m = half n+ rev00 _ _ = error "BraunSeq.reverse: bug!"++ rev11 n x E = (x,E)+ rev11 n x (B y a b)+ | odd n = let (x',a') = rev11 m x a+ (y',b') = rev11 m y b in (y', B x' b' a')+ | otherwise = let (x',a') = rev11 m x a+ (y',b') = rev11 (m-1) y b in (x', B y' a' b')+ where m = half n++ rev01 n E = error "BraunSeq.reverse: bug!"+ rev01 n (B x a b)+ | n == 1 = (x, E)+ | odd n = let (y',a') = rev01 m a+ (x',b') = rev11 m x b in (x', B y' b' a')+ | otherwise = let (y',a') = rev01 m a+ (x',b') = rev11 (m-1) x b in (y', B x' a' b')+ where m = half n++ rev10 n x E = B x E E+ rev10 n x (B y a b)+ | odd n = let a' = rev10 m x a+ (y',b') = rev11 m y b in B y' a' b'+ | otherwise = let (x',a') = rev11 m x a+ b' = rev10 (m-1) y b in B x' b' a'+ where m = half n++fromList = L.lhead . L.foldr build [E] . rows 1+ where rows k [] = []+ rows k xs = (k, ys) : rows (k+k) zs+ where (ys,zs) = L.splitAt k xs++ build (k,xs) ts = zipWithB xs ts1 ts2+ where (ts1, ts2) = L.splitAt k ts++ zipWithB [] _ _ = []+ zipWithB (x:xs) [] _ = singleton x : L.map singleton xs+ zipWithB (x:xs) (t:ts) [] = B x t E : zipWithB xs ts []+ zipWithB (x:xs) (t1:ts1) (t2:ts2) = B x t1 t2 : zipWithB xs ts1 ts2++toList E = []+toList t = tol [t]+ where tol [] = []+ tol ts = xs ++ tol (ts1 ++ ts2)+ where xs = L.map root ts+ (ts1,ts2) = children ts++ children [] = ([],[])+ children (B x E _ : ts) = ([],[])+ children (B x a E : ts) = (a : leftChildren ts, [])+ children (B x a b : ts) = (a : ts1, b : ts2)+ where (ts1, ts2) = children ts+ children _ = error "BraunSeq.toList: bug!"++ leftChildren [] = []+ leftChildren (B x E _ : ts) = []+ leftChildren (B x a b : ts) = a : leftChildren ts+ leftChildren _ = error "BraunSeq.toList: bug!"++ root (B x a b) = x+ root _ = error "BraunSeq.toList: bug!"++ left (B x a b) = a+ left _ = error "BraunSeq.toList: bug!"++map f E = E+map f (B x a b) = B (f x) (map f a) (map f b)++copy n x = if n <= 0 then empty else fst (copy2 n)+ where copy2 n+ | odd n = (B x a a, B x b a)+ | n == 0 = (E, singleton x)+ | otherwise = (B x b a, B x b b)+ where (a, b) = copy2 (half (n-1))++inBounds i xs = (i >= 0) && inb xs i+ where inb E i = False+ inb (B x a b) i+ | odd i = inb a (half i)+ | i == 0 = True+ | otherwise = inb b (half i - 1)++lookup i xs = runIdentity (lookupM i xs)++lookupM i xs+ | i < 0 = fail "BraunSeq.lookupM: bad subscript"+ | otherwise = look xs i+ where look E i = nothing+ look (B x a b) i+ | odd i = look a (half i)+ | i == 0 = return x+ | otherwise = look b (half i - 1)+ nothing = fail "BraunSeq.lookupM: not found"++lookupWithDefault d i xs = if i < 0 then d+ else look xs i+ where look E i = d+ look (B x a b) i+ | odd i = look a (half i)+ | i == 0 = x+ | otherwise = look b (half i - 1)++update i y xs = if i < 0 then xs else upd i xs+ where upd i E = E+ upd i (B x a b)+ | odd i = B x (upd (half i) a) b+ | i == 0 = B y a b+ | otherwise = B x a (upd (half i - 1) b)++adjust f i xs = if i < 0 then xs else adj i xs+ where adj i E = E+ adj i (B x a b)+ | odd i = B x (adj (half i) a) b+ | i == 0 = B (f x) a b+ | otherwise = B x a (adj (half i - 1) b)++mapWithIndex f xs = mwi 0 1 xs+ where mwi i d E = E+ mwi i d (B x a b) = B (f i x) (mwi (i+d) dd a) (mwi (i+dd) dd b)+ where dd = d+d++take n xs = if n <= 0 then E else ta n xs+ where ta n E = E+ ta n (B x a b)+ | odd n = B x (ta m a) (ta m b)+ | n == 0 = E+ | otherwise = B x (ta m a) (ta (m-1) b)+ where m = half n++drop n xs = if n <= 0 then xs else dr n xs+ where dr n E = E+ dr n t@(B x a b)+ | odd n = combine (dr m a) (dr m b)+ | n == 0 = t+ | otherwise = combine (dr (m-1) b) (dr m a)+ where m = half n++zip (B x a b) (B y c d) = B (x,y) (zip a c) (zip b d)+zip _ _ = E++zip3 (B x a b) (B y c d) (B z e f) = B (x,y,z) (zip3 a c e) (zip3 b d f)+zip3 _ _ _ = E++zipWith f (B x a b) (B y c d) = B (f x y) (zipWith f a c) (zipWith f b d)+zipWith f _ _ = E++zipWith3 fn (B x a b) (B y c d) (B z e f) = + B (fn x y z) (zipWith3 fn a c e) (zipWith3 fn b d f)+zipWith3 fn _ _ _ = E++unzip E = (E, E)+unzip (B (x,y) a b) = (B x a1 b1, B y a2 b2)+ where (a1,a2) = unzip a+ (b1,b2) = unzip b++unzip3 E = (E, E, E)+unzip3 (B (x,y,z) a b) = (B x a1 b1, B y a2 b2, B z a3 b3)+ where (a1,a2,a3) = unzip3 a+ (b1,b2,b3) = unzip3 b++unzipWith f g E = (E, E)+unzipWith f g (B x a b) = (B (f x) a1 b1, B (g x) a2 b2)+ where (a1,a2) = unzipWith f g a+ (b1,b2) = unzipWith f g b++unzipWith3 f g h E = (E, E, E)+unzipWith3 f g h (B x a b) = (B (f x) a1 b1, B (g x) a2 b2, B (h x) a3 b3)+ where (a1,a2,a3) = unzipWith3 f g h a+ (b1,b2,b3) = unzipWith3 f g h b+++strict s@E = s+strict s@(B x l r) = strict l `seq` strict r `seq` s++strictWith f s@E = s+strictWith f s@(B x l r) = f x `seq` strictWith f l `seq` strictWith f r `seq` s++-- invariants:+-- * Left subtree is exactily the same size as the right+-- subtree, or one element larger++structuralInvariant E = True+structuralInvariant (B _ l r) = isJust (check l r)++ where check E E = Just 1+ check (B _ E E) E = Just 2+ check (B _ l1 l2) (B _ r1 r2) = do+ x <- check l1 l2+ y <- check r1 r2+ if (x == y) || (x == y + 1)+ then return (x+y+1)+ else fail "unbalanced tree"+ check _ _ = fail "unbalanced tree"+++-- the remaining functions all use defaults++concat = concatUsingFoldr+reverseOnto = reverseOntoUsingReverse+concatMap = concatMapUsingFoldr+fold = foldrUsingLists+fold' f = foldl'UsingLists (flip f)+fold1 = fold1UsingFold+fold1' = fold1'UsingFold'+foldr = foldrUsingLists+foldr' = foldr'UsingLists+foldl = foldlUsingLists+foldl' = foldl'UsingLists+foldr1 = foldr1UsingLists+foldr1' = foldr1'UsingLists+foldl1 = foldl1UsingLists+foldl1' = foldl1UsingLists+reducer = reducerUsingReduce1+reducer' = reducer'UsingReduce1'+reducel = reducelUsingReduce1+reducel' = reducel'UsingReduce1'+reduce1 = reduce1UsingLists+reduce1' = reduce1'UsingLists+foldrWithIndex = foldrWithIndexUsingLists+foldrWithIndex' = foldrWithIndex'UsingLists+foldlWithIndex = foldlWithIndexUsingLists+foldlWithIndex' = foldlWithIndex'UsingLists+splitAt = splitAtDefault+subseq = subseqDefault+filter = filterUsingLists+partition = partitionUsingLists+takeWhile = takeWhileUsingLview+dropWhile = dropWhileUsingLview+splitWhile = splitWhileUsingLview+++-- instances++instance S.Sequence Seq where+ {lcons = lcons; rcons = rcons;+ lview = lview; lhead = lhead; ltail = ltail;+ lheadM = lheadM; ltailM = ltailM; rheadM = rheadM; rtailM = rtailM;+ rview = rview; rhead = rhead; rtail = rtail; null = null;+ 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; reducer' = reducer'; reducel = reducel;+ reducel' = reducel'; reduce1 = reduce1; 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}++instance Functor Seq where+ fmap = map++instance Monad Seq where+ return = singleton+ xs >>= k = concatMap k xs++instance MonadPlus Seq where+ mplus = append+ mzero = empty++-- instance Eq (Seq a) is derived++instance Ord a => Ord (Seq a) where+ compare = defaultCompare++instance Show a => Show (Seq a) where+ showsPrec = showsPrecUsingToList++instance Read a => Read (Seq a) where+ readsPrec = readsPrecUsingFromList++instance Arbitrary a => Arbitrary (Seq a) where+ arbitrary = arbitrary >>= (return . fromList)+ coarbitrary xs = coarbitrary (toList xs)++instance Monoid (Seq a) where+ mempty = empty+ mappend = append
+ src/Data/Edison/Seq/Defaults.hs view
@@ -0,0 +1,513 @@+-- |+-- Module : Data.Edison.Seq.Defaults+-- Copyright : Copyright (c) 1998 Chris Okasaki+-- License : MIT; see COPYRIGHT file for terms and conditions+--+-- Maintainer : robdockins AT fastmail DOT fm+-- Stability : internal (unstable)+-- Portability : GHC, Hugs (MPTC and FD)+--+-- This module provides default implementations of many of+-- the sequence operations. It is used to fill in implementations+-- and is not intended for end users.++module Data.Edison.Seq.Defaults 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.Identity+import Data.Char (isSpace)++import Data.Edison.Prelude+import Data.Edison.Seq+import qualified Data.Edison.Seq.ListSeq as L++rconsUsingAppend :: Sequence s => a -> s a -> s a+rconsUsingAppend x s = append s (singleton x)++rconsUsingFoldr :: Sequence s => a -> s a -> s a+rconsUsingFoldr x s = foldr lcons (singleton x) s++appendUsingFoldr :: Sequence s => s a -> s a -> s a+appendUsingFoldr s t | null t = s+ | otherwise = foldr lcons t s++rviewDefault :: (Monad m, Sequence s) => s a -> m (a, s a)+rviewDefault xs+ | null xs = fail $ instanceName xs ++ ".rview: empty sequence"+ | otherwise = return (rhead xs, rtail xs)+++rtailUsingLview :: (Sequence s) => s a -> s a+rtailUsingLview xs = + case lview xs of+ Nothing -> error $ instanceName xs ++ ".rtail: empty sequence"+ Just (x, xs) -> rt x xs+ where rt x xs =+ case lview xs of+ Nothing -> empty+ Just (y, ys) -> lcons x (rt y ys)++rtailMUsingLview :: (Monad m,Sequence s) => s a -> m (s a)+rtailMUsingLview xs = + case lview xs of+ Nothing -> fail $ instanceName xs ++ ".rtailM: empty sequence"+ Just (x, xs) -> return (rt x xs)+ where rt x xs =+ case lview xs of+ Nothing -> empty+ Just (y, ys) -> lcons x (rt y ys)++++concatUsingFoldr :: Sequence s => s (s a) -> s a+concatUsingFoldr = foldr append empty++reverseUsingReverseOnto :: Sequence s => s a -> s a+reverseUsingReverseOnto s = reverseOnto s empty++reverseUsingLists :: Sequence s => s a -> s a+reverseUsingLists = fromList . L.reverse . toList++reverseOntoUsingFoldl :: Sequence s => s a -> s a -> s a+reverseOntoUsingFoldl xs ys = foldl (flip lcons) ys xs++reverseOntoUsingReverse :: Sequence s => s a -> s a -> s a+reverseOntoUsingReverse = append . reverse++fromListUsingCons :: Sequence s => [a] -> s a+fromListUsingCons = L.foldr lcons empty++toListUsingFoldr :: Sequence s => s a -> [a]+toListUsingFoldr = foldr (:) []++mapUsingFoldr :: Sequence s => (a -> b) -> s a -> s b+mapUsingFoldr f = foldr (lcons . f) empty++concatMapUsingFoldr :: Sequence s => (a -> s b) -> s a -> s b+concatMapUsingFoldr f = foldr (append . f) empty++foldrUsingLists :: Sequence s => (a -> b -> b) -> b -> s a -> b+foldrUsingLists f e xs = L.foldr f e (toList xs)++foldr'UsingLists :: Sequence s => (a -> b -> b) -> b -> s a -> b+foldr'UsingLists f e xs = L.foldr' f e (toList xs)++foldlUsingLists :: Sequence s => (b -> a -> b) -> b -> s a -> b+foldlUsingLists f e xs = L.foldl f e (toList xs)++foldl'UsingLists :: Sequence s => (b -> a -> b) -> b -> s a -> b+foldl'UsingLists f e xs = L.foldl' f e (toList xs)++foldr1UsingLists :: Sequence s => (a -> a -> a) -> s a -> a+foldr1UsingLists f xs = L.foldr1 f (toList xs)++foldr1'UsingLists :: Sequence s => (a -> a -> a) -> s a -> a+foldr1'UsingLists f xs = L.foldr1' f (toList xs)++foldl1UsingLists :: Sequence s => (a -> a -> a) -> s a -> a+foldl1UsingLists f xs = L.foldl1 f (toList xs)++foldl1'UsingLists :: Sequence s => (a -> a -> a) -> s a -> a+foldl1'UsingLists f xs = L.foldl1' f (toList xs)++fold1UsingFold :: Sequence s => (a -> a -> a) -> s a -> a+fold1UsingFold f xs =+ case lview xs of+ Nothing -> error $ instanceName xs ++ ".fold1: empty sequence"+ Just (x, xs) -> fold f x xs++fold1'UsingFold' :: Sequence s => (a -> a -> a) -> s a -> a+fold1'UsingFold' f xs =+ case lview xs of+ Nothing -> error $ instanceName xs ++ ".fold1': empty sequence"+ Just (x, xs) -> fold' f x xs++foldr1UsingLview :: Sequence s => (a -> a -> a) -> s a -> a+foldr1UsingLview f xs = + case lview xs of+ Nothing -> error $ instanceName xs ++ ".foldr1: empty sequence"+ Just (x, xs) -> fr1 x xs+ where fr1 x xs =+ case lview xs of+ Nothing -> x+ Just (y,ys) -> f x (fr1 y ys)++foldr1'UsingLview :: Sequence s => (a -> a -> a) -> s a -> a+foldr1'UsingLview f xs =+ case lview xs of+ Nothing -> error $ instanceName xs ++ ".foldr1': empty sequence"+ Just (x,xs) -> fr1 x xs+ where fr1 x xs = + case lview xs of+ Nothing -> x+ Just (y,ys) -> f x $! (fr1 y ys)++foldl1UsingFoldl :: Sequence s => (a -> a -> a) -> s a -> a+foldl1UsingFoldl f xs = + case lview xs of+ Nothing -> error $ instanceName xs ++ ".foldl1: empty sequence"+ Just (x,xs) -> foldl f x xs++foldl1'UsingFoldl' :: Sequence s => (a -> a -> a) -> s a -> a+foldl1'UsingFoldl' f xs =+ case lview xs of+ Nothing -> error $ instanceName xs ++ ".foldl1': empty sequence"+ Just (x,xs) -> foldl' f x xs++reducerUsingReduce1 :: Sequence s => (a -> a -> a) -> a -> s a -> a+reducerUsingReduce1 f e s+ | null s = e+ | otherwise = f (reduce1 f s) e++reducer'UsingReduce1' :: Sequence s => (a -> a -> a) -> a -> s a -> a+reducer'UsingReduce1' f e s+ | null s = e+ | otherwise = f (reduce1' f s) e++reducelUsingReduce1 :: Sequence s => (a -> a -> a) -> a -> s a -> a+reducelUsingReduce1 f e s+ | null s = e+ | otherwise = f e (reduce1 f s)++reducel'UsingReduce1' :: Sequence s => (a -> a -> a) -> a -> s a -> a+reducel'UsingReduce1' f e s+ | null s = e+ | otherwise = f e (reduce1' f s)++reduce1UsingLists :: Sequence s => (a -> a -> a) -> s a -> a+reduce1UsingLists f s = L.reduce1 f (toList s)++reduce1'UsingLists :: Sequence s => (a -> a -> a) -> s a -> a+reduce1'UsingLists f s = L.reduce1' f (toList s)++copyUsingLists :: Sequence s => Int -> a -> s a+copyUsingLists n x = fromList (L.copy n x)+++inBoundsUsingDrop :: Sequence s => Int -> s a -> Bool+inBoundsUsingDrop i s = + i >= 0 && not (null (drop i s))++inBoundsUsingLookupM :: Sequence s => Int -> s a -> Bool+inBoundsUsingLookupM i s =+ case lookupM i s of+ Just x -> True+ Nothing -> False++inBoundsUsingSize :: Sequence s => Int -> s a -> Bool+inBoundsUsingSize i s = i >= 0 && i < size s++lookupUsingLookupM :: Sequence s => Int -> s a -> a+lookupUsingLookupM i s = runIdentity (lookupM i s)++lookupUsingDrop :: Sequence s => Int -> s a -> a+lookupUsingDrop i s+ | i < 0 || null s' = error $ instanceName s ++ ".lookup: bad subscript"+ | otherwise = lhead s'+ where s' = drop i s++lookupWithDefaultUsingLookupM :: Sequence s => a -> Int -> s a -> a+lookupWithDefaultUsingLookupM d i s =+ case lookupM i s of+ Nothing -> d+ Just x -> x++lookupWithDefaultUsingDrop :: Sequence s => a -> Int -> s a -> a+lookupWithDefaultUsingDrop d i s+ | i < 0 || null s' = d+ | otherwise = lhead s'+ where s' = drop i s++lookupMUsingDrop :: (Monad m, Sequence s) => Int -> s a -> m a+lookupMUsingDrop i s+ -- XXX better error message!+ | i < 0 || null s' = fail $ instanceName s+ ++ ".lookupMUsingDrop: empty sequence"+ | otherwise = return (lhead s')+ where s' = drop i s++filterUsingLview :: Sequence s => (a -> Bool) -> s a -> s a+filterUsingLview p xs =+ case lview xs of+ Nothing -> empty+ Just (x,xs) -> if p x then lcons x (filter p xs) else filter p xs++filterUsingLists :: Sequence s => (a -> Bool) -> s a -> s a+filterUsingLists p xs =+ fromList (L.filter p (toList xs))++filterUsingFoldr :: Sequence s => (a -> Bool) -> s a -> s a+filterUsingFoldr p = foldr pcons empty+ where pcons x xs = if p x then lcons x xs else xs++partitionUsingLists :: Sequence s => (a -> Bool) -> s a -> (s a, s a)+partitionUsingLists p xs =+ let (ys,zs) = L.partition p (toList xs)+ in (fromList ys, fromList zs)++partitionUsingFoldr :: Sequence s => (a -> Bool) -> s a -> (s a, s a)+partitionUsingFoldr p = foldr pcons (empty, empty)+ where pcons x (xs, xs') = if p x then (lcons x xs, xs') else (xs, lcons x xs')++updateUsingAdjust :: Sequence s => Int -> a -> s a -> s a+updateUsingAdjust i y = adjust (const y) i++updateUsingSplitAt :: Sequence s => Int -> a -> s a -> s a+updateUsingSplitAt i x xs+ | i < 0 = xs+ | otherwise = let (ys,zs) = splitAt i xs+ in if null zs then xs else append ys (lcons x (ltail zs))++adjustUsingLists :: Sequence s => (a -> a) -> Int -> s a -> s a+adjustUsingLists f i xs = fromList (L.adjust f i (toList xs))++adjustUsingSplitAt :: Sequence s => (a -> a) -> Int -> s a -> s a+adjustUsingSplitAt f i xs+ | i < 0 = xs+ | otherwise = let (ys,zs) = splitAt i xs+ in case lview zs of+ Nothing -> xs+ Just (z,zs') -> append ys (lcons (f z) zs')++{-+insertAtUsingLists :: Sequence s => Int -> a -> s a -> s a+insertAtUsingLists i x xs = + fromList (L.insertAt i x (toList xs))++insertAtUsingSplitAt :: Sequence s => Int -> a -> s a -> s a+insertAtUsingSplitAt i x xs+ | (xs_before, xs_after) <- splitAt i xs =+ append xs_before (lcons x xs_after)++deleteAtUsingLists :: Sequence s => Int -> s a -> s a+deleteAtUsingLists i xs = fromList (L.deleteAt i (toList xs))++deleteAtUsingSplitAt :: Sequence s => Int -> s a -> s a+deleteAtUsingSplitAt i xs+ | (xs_before, xs_after) <- splitAt i xs =+ append xs_before (ltail xs_after)+-}++mapWithIndexUsingLists :: Sequence s => (Int -> a -> b) -> s a -> s b+mapWithIndexUsingLists f xs = fromList (L.mapWithIndex f (toList xs))++foldrWithIndexUsingLists :: + Sequence s => (Int -> a -> b -> b) -> b -> s a -> b+foldrWithIndexUsingLists f e xs = L.foldrWithIndex f e (toList xs)++foldrWithIndex'UsingLists :: + Sequence s => (Int -> a -> b -> b) -> b -> s a -> b+foldrWithIndex'UsingLists f e xs = L.foldrWithIndex' f e (toList xs)++foldlWithIndexUsingLists :: + Sequence s => (b -> Int -> a -> b) -> b -> s a -> b+foldlWithIndexUsingLists f e xs = L.foldlWithIndex f e (toList xs)++foldlWithIndex'UsingLists :: + Sequence s => (b -> Int -> a -> b) -> b -> s a -> b+foldlWithIndex'UsingLists f e xs = L.foldlWithIndex' f e (toList xs)++takeUsingLists :: Sequence s => Int -> s a -> s a+takeUsingLists i s = fromList (L.take i (toList s))++takeUsingLview :: Sequence s => Int -> s a -> s a+takeUsingLview i xs+ | i <= 0 = empty+ | otherwise = case lview xs of+ Nothing -> empty+ Just (x,xs') -> lcons x (take (i-1) xs')++dropUsingLists :: Sequence s => Int -> s a -> s a+dropUsingLists i s = fromList (L.drop i (toList s))++dropUsingLtail :: Sequence s => Int -> s a -> s a+dropUsingLtail i xs+ | i <= 0 || null xs = xs+ | otherwise = dropUsingLtail (i-1) (ltail xs)++splitAtDefault :: Sequence s => Int -> s a -> (s a, s a)+splitAtDefault i s = (take i s, drop i s)++splitAtUsingLview :: Sequence s => Int -> s a -> (s a, s a)+splitAtUsingLview i xs+ | i <= 0 = (empty,xs)+ | otherwise = case lview xs of+ Nothing -> (empty,empty)+ Just (x,xs') -> (lcons x ys,zs)+ where (ys,zs) = splitAtUsingLview (i-1) xs'++subseqDefault :: Sequence s => Int -> Int -> s a -> s a+subseqDefault i len xs = take len (drop i xs)++takeWhileUsingLview :: Sequence s => (a -> Bool) -> s a -> s a+takeWhileUsingLview p xs =+ case lview xs of+ Just (x,xs') | p x -> lcons x (takeWhileUsingLview p xs')+ _ -> empty++dropWhileUsingLview :: Sequence s => (a -> Bool) -> s a -> s a+dropWhileUsingLview p xs =+ case lview xs of+ Just (x,xs') | p x -> dropWhileUsingLview p xs'+ _ -> xs++splitWhileUsingLview :: Sequence s => (a -> Bool) -> s a -> (s a, s a)+splitWhileUsingLview p xs =+ case lview xs of+ Just (x,xs') | p x -> let (front, back) = splitWhileUsingLview p xs'+ in (lcons x front, back)+ _ -> (empty, xs)++zipUsingLview :: Sequence s => s a -> s b -> s (a,b)+zipUsingLview xs ys =+ case lview xs of+ Nothing -> empty+ Just (x,xs') ->+ case lview ys of+ Nothing -> empty+ Just (y,ys') -> lcons (x,y) (zipUsingLview xs' ys')++zip3UsingLview :: Sequence s => s a -> s b -> s c -> s (a,b,c)+zip3UsingLview xs ys zs =+ case lview xs of+ Nothing -> empty+ Just (x,xs') ->+ case lview ys of+ Nothing -> empty+ Just (y,ys') ->+ case lview zs of+ Nothing -> empty+ Just (z,zs') -> lcons (x,y,z) (zip3UsingLview xs' ys' zs')++zipWithUsingLview :: Sequence s => (a -> b -> c) -> s a -> s b -> s c+zipWithUsingLview f xs ys =+ case lview xs of+ Nothing -> empty+ Just (x,xs') ->+ case lview ys of+ Nothing -> empty+ Just (y,ys') -> lcons (f x y) (zipWithUsingLview f xs' ys')++zipWith3UsingLview :: + Sequence s => (a -> b -> c -> d) -> s a -> s b -> s c -> s d+zipWith3UsingLview f xs ys zs =+ case lview xs of+ Nothing -> empty+ Just (x,xs') ->+ case lview ys of+ Nothing -> empty+ Just (y,ys') ->+ case lview zs of+ Nothing -> empty+ Just (z,zs') -> lcons (f x y z) (zipWith3UsingLview f xs' ys' zs')++zipUsingLists :: Sequence s => s a -> s b -> s (a,b)+zipUsingLists xs ys = fromList (L.zip (toList xs) (toList ys))++zip3UsingLists :: Sequence s => s a -> s b -> s c -> s (a,b,c)+zip3UsingLists xs ys zs = + fromList (L.zip3 (toList xs) (toList ys) (toList zs))++zipWithUsingLists :: Sequence s => (a -> b -> c) -> s a -> s b -> s c+zipWithUsingLists f xs ys =+ fromList (L.zipWith f (toList xs) (toList ys))++zipWith3UsingLists :: + Sequence s => (a -> b -> c -> d) -> s a -> s b -> s c -> s d+zipWith3UsingLists f xs ys zs =+ fromList (L.zipWith3 f (toList xs) (toList ys) (toList zs))++unzipUsingLists :: Sequence s => s (a,b) -> (s a, s b)+unzipUsingLists xys =+ case L.unzip (toList xys) of+ (xs, ys) -> (fromList xs, fromList ys)++unzipUsingFoldr :: Sequence s => s (a,b) -> (s a, s b)+unzipUsingFoldr = foldr pcons (empty,empty) + where pcons (x,y) (xs,ys) = (lcons x xs, lcons y ys)++unzip3UsingLists :: Sequence s => s (a,b,c) -> (s a, s b, s c)+unzip3UsingLists xyzs =+ case L.unzip3 (toList xyzs) of+ (xs, ys, zs) -> (fromList xs, fromList ys, fromList zs)++unzip3UsingFoldr :: Sequence s => s (a,b,c) -> (s a, s b, s c)+unzip3UsingFoldr = foldr tcons (empty,empty,empty)+ where tcons (x,y,z) (xs,ys,zs) = (lcons x xs, lcons y ys, lcons z zs)++unzipWithUsingLists :: + Sequence s => (a -> b) -> (a -> c) -> s a -> (s b, s c)+unzipWithUsingLists f g xys =+ case L.unzipWith f g (toList xys) of+ (xs, ys) -> (fromList xs, fromList ys)++unzipWithUsingFoldr :: + Sequence s => (a -> b) -> (a -> c) -> s a -> (s b, s c)+unzipWithUsingFoldr f g = foldr pcons (empty,empty) + where pcons e (xs,ys) = (lcons (f e) xs, lcons (g e) ys)++unzipWith3UsingLists :: + Sequence s => (a -> b) -> (a -> c) -> (a -> d) -> s a -> (s b, s c, s d)+unzipWith3UsingLists f g h xyzs =+ case L.unzipWith3 f g h (toList xyzs) of+ (xs, ys, zs) -> (fromList xs, fromList ys, fromList zs)++unzipWith3UsingFoldr :: + Sequence s => (a -> b) -> (a -> c) -> (a -> d) -> s a -> (s b, s c, s d)+unzipWith3UsingFoldr f g h = foldr tcons (empty,empty,empty) + where tcons e (xs,ys,zs) = (lcons (f e) xs, lcons (g e) ys, lcons (h e) zs)++showsPrecUsingToList :: (Show a,Sequence s) => Int -> s a -> ShowS+showsPrecUsingToList i xs rest+ | i == 0 = concat [ instanceName xs,".fromList "] ++ showsPrec 10 (toList xs) rest+ | otherwise = concat ["(",instanceName xs,".fromList "] ++ showsPrec 10 (toList xs) (')':rest)++readsPrecUsingFromList :: (Read a,Sequence s) => Int -> ReadS (s a)+readsPrecUsingFromList i xs =+ let result = maybeParens p xs+ p xs = tokenMatch ((instanceName x)++".fromList") xs+ >>= readsPrec 10+ >>= \(l,rest) -> return (fromList l,rest)++ -- play games with the typechecker so we don't have to use+ -- extensions for scoped type variables+ ~[(x,_)] = result++ in result++defaultCompare :: (Ord a, Sequence s) => s a -> s a -> Ordering+defaultCompare a b =+ case (lview a, lview b) of+ (Nothing, Nothing) -> EQ+ (Nothing, _ ) -> LT+ (_ , Nothing) -> GT+ (Just (x,xs), Just (y,ys)) ->+ case compare x y of+ EQ -> defaultCompare xs ys+ c -> c+++dropMatch :: (Eq a,MonadPlus m) => [a] -> [a] -> m [a]+dropMatch [] ys = return ys+dropMatch (x:xs) (y:ys)+ | x == y = dropMatch xs ys+ | otherwise = mzero+dropMatch _ _ = mzero++tokenMatch :: MonadPlus m => String -> String -> m String+tokenMatch token str = dropMatch token (munch str) >>= return . munch+ where munch = dropWhile isSpace++readSParens :: ReadS a -> ReadS a+readSParens p xs = return xs+ >>= tokenMatch "("+ >>= p+ >>= \(x,xs') -> return xs'+ >>= tokenMatch ")"+ >>= \rest -> return (x,rest)++maybeParens :: ReadS a -> ReadS a+maybeParens p xs = readSParens p xs `mplus` p xs
+ src/Data/Edison/Seq/FingerSeq.hs view
@@ -0,0 +1,375 @@+-- |+-- Module : Data.Edison.Seq.FingerSeq+-- 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)+++module Data.Edison.Seq.FingerSeq (+ -- * Sequence Type+ Seq, -- instance of Sequence, Functor, Monad, MonadPlus++ -- * Sequence Operations+ empty,singleton,lcons,rcons,append,lview,lhead,ltail,rview,rhead,rtail,+ lheadM,ltailM,rheadM,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,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 qualified Prelude+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 Data.Edison.Prelude+import qualified Data.Edison.Seq as S+import Data.Edison.Seq.Defaults+import Control.Monad+import Control.Monad.Identity+import Data.Monoid+import Test.QuickCheck++#ifdef __GLASGOW_HASKELL__+import GHC.Base (unsafeCoerce#)+#endif+++import qualified Data.Edison.Concrete.FingerTree as FT++moduleName :: String+moduleName = "Data.Edison.Seq.FingerSeq"+++newtype SizeM = SizeM Int deriving (Eq,Ord,Num,Enum,Show)+unSizeM (SizeM x) = x++instance Monoid SizeM where+ mempty = 0+ mappend = (+)+++newtype Elem a = Elem a+unElem (Elem x) = x++instance Measured SizeM (Elem a) where+ measure _ = 1++newtype Seq a = Seq (FT.FingerTree SizeM (Elem a))+unSeq (Seq ft) = ft++++empty :: Seq a+singleton :: a -> Seq a+lcons :: a -> Seq a -> Seq a+rcons :: a -> Seq a -> Seq a+append :: Seq a -> Seq a -> Seq a+lview :: (Monad m) => Seq a -> m (a, Seq a)+lhead :: Seq a -> a+lheadM :: (Monad m) => Seq a -> m a+ltail :: Seq a -> Seq a+ltailM :: (Monad m) => Seq a -> m (Seq a)+rview :: (Monad m) => Seq a -> m (a, Seq a)+rhead :: Seq a -> a+rheadM :: (Monad m) => Seq a -> m a+rtail :: Seq a -> Seq a+rtailM :: (Monad m) => Seq a -> m (Seq a)+null :: Seq a -> Bool+size :: Seq a -> Int+concat :: Seq (Seq a) -> Seq a+reverse :: Seq a -> Seq a+reverseOnto :: Seq a -> Seq a -> Seq a+fromList :: [a] -> Seq a+toList :: Seq a -> [a]+map :: (a -> b) -> Seq a -> Seq b+concatMap :: (a -> Seq b) -> Seq a -> Seq b+fold :: (a -> b -> b) -> b -> Seq a -> b+fold' :: (a -> b -> b) -> b -> Seq a -> b+fold1 :: (a -> a -> a) -> Seq a -> a+fold1' :: (a -> a -> a) -> Seq a -> a+foldr :: (a -> b -> b) -> b -> Seq a -> b+foldl :: (b -> a -> b) -> b -> Seq a -> b+foldr1 :: (a -> a -> a) -> Seq a -> a+foldl1 :: (a -> a -> a) -> Seq a -> a+reducer :: (a -> a -> a) -> a -> Seq a -> a+reducel :: (a -> a -> a) -> a -> Seq a -> a+reduce1 :: (a -> a -> a) -> Seq a -> a+foldr' :: (a -> b -> b) -> b -> Seq a -> b+foldl' :: (b -> a -> b) -> b -> Seq a -> b+foldr1' :: (a -> a -> a) -> Seq a -> a+foldl1' :: (a -> a -> a) -> Seq a -> a+reducer' :: (a -> a -> a) -> a -> Seq a -> a+reducel' :: (a -> a -> a) -> a -> Seq a -> a+reduce1' :: (a -> a -> a) -> Seq a -> a+copy :: Int -> a -> Seq a+inBounds :: Int -> Seq a -> Bool+lookup :: Int -> Seq a -> a+lookupM :: (Monad m) => Int -> Seq a -> m a+lookupWithDefault :: a -> Int -> Seq a -> a+update :: Int -> a -> Seq a -> Seq a+adjust :: (a -> a) -> Int -> Seq a -> Seq a+mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b+foldrWithIndex :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex :: (b -> Int -> a -> b) -> b -> Seq a -> b+foldrWithIndex' :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex' :: (b -> Int -> a -> b) -> b -> Seq a -> b+take :: Int -> Seq a -> Seq a+drop :: Int -> Seq a -> Seq a+splitAt :: Int -> Seq a -> (Seq a, Seq a)+subseq :: Int -> Int -> Seq a -> Seq a+filter :: (a -> Bool) -> Seq a -> Seq a+partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+takeWhile :: (a -> Bool) -> Seq a -> Seq a+dropWhile :: (a -> Bool) -> Seq a -> Seq a+splitWhile :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+zip :: Seq a -> Seq b -> Seq (a,b)+zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c)+zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c+zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d+unzip :: Seq (a,b) -> (Seq a, Seq b)+unzip3 :: Seq (a,b,c) -> (Seq a, Seq b, Seq c)+unzipWith :: (a -> b) -> (a -> c) -> Seq a -> (Seq b, Seq c)+unzipWith3 :: (a -> b) -> (a -> c) -> (a -> d) -> Seq a -> (Seq b, Seq c, Seq d)+strict :: Seq a -> Seq a+strictWith :: (a -> b) -> Seq a -> Seq a+structuralInvariant :: Seq a -> Bool++#ifdef __GLASGOW_HASKELL__++mapElem = unsafeCoerce#+mapUnElem = unsafeCoerce#++#else++mapElem = Prelude.map Elem+mapUnElem = Prelude.map unElem++#endif++null = FT.null . unSeq+empty = Seq FT.empty+singleton = Seq . FT.singleton . Elem+lcons x = Seq . FT.lcons (Elem x) . unSeq+rcons x = Seq . FT.rcons (Elem x) . unSeq+append p q = Seq $ FT.append (unSeq p) (unSeq q)+fromList = Seq . FT.fromList . mapElem+toList = mapUnElem . FT.toList . unSeq+reverse = Seq . FT.reverse . unSeq+size = unSizeM . measure . unSeq+strict = Seq . FT.strict . unSeq+strictWith f = Seq . FT.strictWith (f . unElem) . unSeq+structuralInvariant = FT.structuralInvariant . unSeq++#ifdef __GLASGOW_HASKELL__++lview (Seq xs) =+ let f = unsafeCoerce# :: Monad m => m (Elem a,FT.FingerTree SizeM (Elem a)) -> m (a,Seq a)+ in f (FT.lview xs)++rview (Seq xs) =+ let f = unsafeCoerce# :: Monad m => m (Elem a,FT.FingerTree SizeM (Elem a)) -> m (a,Seq a)+ in f (FT.rview xs)++#else++lview (Seq xs) = FT.lview xs >>= \(Elem a, zs) -> return (a, Seq zs)+rview (Seq xs) = FT.rview xs >>= \(Elem a, zs) -> return (a, Seq zs)++#endif+++lheadM xs = lview xs >>= return . fst+ltailM xs = lview xs >>= return . snd+rheadM xs = rview xs >>= return . fst+rtailM xs = rview xs >>= return . snd+lhead = runIdentity . lheadM+ltail = runIdentity . ltailM+rhead = runIdentity . rheadM+rtail = runIdentity . rtailM++fold = foldr+fold' = foldr'+fold1 = foldr1+fold1' = foldr1'++#ifdef __GLASGOW_HASKELL__++foldr f z (Seq xs) = unElem $ FT.foldFT id (.) (unsafeCoerce# f) xs (Elem z)+foldr' f z (Seq xs) = unElem $ FT.foldFT id (.) (unsafeCoerce# f) xs (Elem z)++reduce1 f (Seq xs) = unElem $ FT.reduce1 (unsafeCoerce# f) xs+reduce1' f (Seq xs) = unElem $ FT.reduce1' (unsafeCoerce# f) xs++map f (Seq xs) = Seq $ FT.mapTree (unsafeCoerce# f) xs++#else++foldr f z (Seq xs) = unElem $ FT.foldFT id (.) ( \(Elem x) (Elem y) -> Elem $ f x y) xs (Elem z)+foldr' f z (Seq xs) = unElem $ FT.foldFT id (.) ( \(Elem x) (Elem y) -> Elem $ f x y) xs (Elem z)++reduce1 f (Seq xs) = unElem $ FT.reduce1 ( \(Elem x) (Elem y) -> Elem $ f x y) xs+reduce1' f (Seq xs) = unElem $ FT.reduce1' ( \(Elem x) (Elem y) -> Elem $ f x y) xs++map f (Seq xs) = Seq $ FT.mapTree ( \(Elem x) -> Elem $ f x) xs++#endif++lookupM i (Seq xs)+ | inBounds i (Seq xs) =+ case FT.splitTree (> (SizeM i)) (SizeM 0) xs of+ FT.Split _ (Elem x) _ -> return x++ | otherwise = fail "FingerSeq.lookupM: index out of bounds"++lookupWithDefault d i (Seq xs)+ | inBounds i (Seq xs) =+ case FT.splitTree (> (SizeM i)) (SizeM 0) xs of+ FT.Split _ (Elem x) _ -> x++ | otherwise = d++update i x (Seq xs)+ | inBounds i (Seq xs) =+ case FT.splitTree (> (SizeM i)) (SizeM 0) xs of+ FT.Split l _ r -> Seq $ FT.append l $ FT.lcons (Elem x) $ r++ | otherwise = Seq xs++adjust f i (Seq xs)+ | inBounds i (Seq xs) =+ case FT.splitTree (> (SizeM i)) (SizeM 0) xs of+ FT.Split l x r -> Seq $ FT.append l $ FT.lcons (Elem (f (unElem x))) $ r++ | otherwise = Seq xs++take i (Seq xs) = Seq $ FT.takeUntil (> (SizeM i)) xs+drop i (Seq xs) = Seq $ FT.dropUntil (> (SizeM i)) xs+splitAt i (Seq xs) = let (a,b) = FT.split (> (SizeM i)) xs in (Seq a, Seq b)+++inBounds = inBoundsUsingSize+lookup = lookupUsingLookupM++foldr1 f xs =+ case rview xs of+ Nothing -> error "FingerSeq.foldr1: empty sequence"+ Just (x,xs') -> foldr f x xs'++foldr1' f xs =+ case rview xs of+ Nothing -> error "FingerSeq.foldr1': empty sequence"+ Just (x,xs') -> foldr' f x xs'++foldl = foldlUsingLists+foldl' = foldl'UsingLists+foldl1 = foldl1UsingLists+foldl1' = foldl1'UsingLists++reducer = reducerUsingReduce1+reducer' = reducer'UsingReduce1'+reducel = reducelUsingReduce1+reducel' = reducel'UsingReduce1'++copy = copyUsingLists+concat = concatUsingFoldr+reverseOnto = reverseOntoUsingReverse+concatMap = concatMapUsingFoldr+subseq = subseqDefault+filter = filterUsingLview+partition = partitionUsingFoldr+takeWhile = takeWhileUsingLview+dropWhile = dropWhileUsingLview+splitWhile = splitWhileUsingLview++mapWithIndex = mapWithIndexUsingLists+foldrWithIndex = foldrWithIndexUsingLists+foldrWithIndex' = foldrWithIndex'UsingLists+foldlWithIndex = foldlWithIndexUsingLists+foldlWithIndex' = foldlWithIndex'UsingLists++zip = zipUsingLview+zip3 = zip3UsingLview+zipWith = zipWithUsingLview+zipWith3 = zipWith3UsingLview++unzip = unzipUsingFoldr+unzip3 = unzip3UsingFoldr+unzipWith = unzipWithUsingFoldr+unzipWith3 = unzipWith3UsingFoldr++-- instances++instance S.Sequence Seq where+ {lcons = lcons; rcons = rcons;+ lview = lview; lhead = lhead; ltail = ltail;+ lheadM = lheadM; ltailM = ltailM; rheadM = rheadM; rtailM = rtailM;+ rview = rview; rhead = rhead; rtail = rtail; null = null;+ 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; reducer' = reducer'; reducel = reducel;+ reducel' = reducel'; reduce1 = reduce1; reduce1' = reduce1';+ copy = copy; inBounds = inBounds; lookup = lookup;+ lookupM = lookupM; lookupWithDefault = lookupWithDefault;+ update = update; adjust = adjust; mapWithIndex = mapWithIndex;+ foldrWithIndex = foldrWithIndex; foldlWithIndex = foldlWithIndex;+ foldrWithIndex' = foldrWithIndex'; 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}++instance Functor Seq where+ fmap = map++instance Monad Seq where+ return = singleton+ xs >>= k = concatMap k xs++instance MonadPlus Seq where+ mplus = append+ mzero = empty++instance Eq a => Eq (Seq a) where+ xs == ys = toList xs == toList ys++instance Ord a => Ord (Seq a) where+ compare = defaultCompare++instance Show a => Show (Seq a) where+ showsPrec = showsPrecUsingToList++instance Read a => Read (Seq a) where+ readsPrec = readsPrecUsingFromList++instance Arbitrary a => Arbitrary (Elem a) where+ arbitrary = arbitrary >>= return . Elem+ coarbitrary = coarbitrary . unElem++instance Arbitrary a => Arbitrary (Seq a) where+ arbitrary = arbitrary >>= return . Seq+ coarbitrary = coarbitrary . unSeq++instance Monoid (Seq a) where+ mempty = empty+ mappend = append
+ src/Data/Edison/Seq/JoinList.hs view
@@ -0,0 +1,427 @@+-- |+-- Module : Data.Edison.Seq.JoinList+-- 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)+--+-- Join lists. All running times are as listed in "Data.Edison.Seq" except+-- for the following:+--+-- * rcons, append @O( 1 )@+--+-- * ltail*, lview @O( 1 )@ when used single-threaded, @O( n )@ otherwise+--+-- * lhead* @O( n )@+--+-- * inBounds, lookup @O( n )@+--+-- * copy @O( log i )@+--+-- * concat @O( n1 )@+--+-- * concatMap, (>>=) @O( n * t )@, where @n@ is the length of the input sequence and+-- @t@ is the running time of @f@++module Data.Edison.Seq.JoinList (+ -- * Sequence Type+ Seq, -- instance of Sequence, Functor, Monad, MonadPlus++ -- * Sequence Operations+ empty,singleton,lcons,rcons,append,lview,lhead,ltail,rview,rhead,rtail,+ lheadM,ltailM,rheadM,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,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 Data.Edison.Prelude+import qualified Data.Edison.Seq as S ( Sequence(..) )+import Data.Edison.Seq.Defaults+import Control.Monad+import Data.Monoid+import Test.QuickCheck++-- signatures for exported functions+moduleName :: String+empty :: Seq a+singleton :: a -> Seq a+lcons :: a -> Seq a -> Seq a+rcons :: a -> Seq a -> Seq a+append :: Seq a -> Seq a -> Seq a+lview :: (Monad m) => Seq a -> m (a, Seq a)+lhead :: Seq a -> a+lheadM :: (Monad m) => Seq a -> m a+ltail :: Seq a -> Seq a+ltailM :: (Monad m) => Seq a -> m (Seq a)+rview :: (Monad m) => Seq a -> m (a, Seq a)+rhead :: Seq a -> a+rheadM :: (Monad m) => Seq a -> m a+rtail :: Seq a -> Seq a+rtailM :: (Monad m) => Seq a -> m (Seq a)+null :: Seq a -> Bool+size :: Seq a -> Int+concat :: Seq (Seq a) -> Seq a+reverse :: Seq a -> Seq a+reverseOnto :: Seq a -> Seq a -> Seq a+fromList :: [a] -> Seq a+toList :: Seq a -> [a]+map :: (a -> b) -> Seq a -> Seq b+concatMap :: (a -> Seq b) -> Seq a -> Seq b+fold :: (a -> b -> b) -> b -> Seq a -> b+fold' :: (a -> b -> b) -> b -> Seq a -> b+fold1 :: (a -> a -> a) -> Seq a -> a+fold1' :: (a -> a -> a) -> Seq a -> a+foldr :: (a -> b -> b) -> b -> Seq a -> b+foldl :: (b -> a -> b) -> b -> Seq a -> b+foldr1 :: (a -> a -> a) -> Seq a -> a+foldl1 :: (a -> a -> a) -> Seq a -> a+reducer :: (a -> a -> a) -> a -> Seq a -> a+reducel :: (a -> a -> a) -> a -> Seq a -> a+reduce1 :: (a -> a -> a) -> Seq a -> a+foldr' :: (a -> b -> b) -> b -> Seq a -> b+foldl' :: (b -> a -> b) -> b -> Seq a -> b+foldr1' :: (a -> a -> a) -> Seq a -> a+foldl1' :: (a -> a -> a) -> Seq a -> a+reducer' :: (a -> a -> a) -> a -> Seq a -> a+reducel' :: (a -> a -> a) -> a -> Seq a -> a+reduce1' :: (a -> a -> a) -> Seq a -> a+copy :: Int -> a -> Seq a+inBounds :: Int -> Seq a -> Bool+lookup :: Int -> Seq a -> a+lookupM :: (Monad m) => Int -> Seq a -> m a+lookupWithDefault :: a -> Int -> Seq a -> a+update :: Int -> a -> Seq a -> Seq a+adjust :: (a -> a) -> Int -> Seq a -> Seq a+mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b+foldrWithIndex :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex :: (b -> Int -> a -> b) -> b -> Seq a -> b+foldrWithIndex' :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex' :: (b -> Int -> a -> b) -> b -> Seq a -> b+take :: Int -> Seq a -> Seq a+drop :: Int -> Seq a -> Seq a+splitAt :: Int -> Seq a -> (Seq a, Seq a)+subseq :: Int -> Int -> Seq a -> Seq a+filter :: (a -> Bool) -> Seq a -> Seq a+partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+takeWhile :: (a -> Bool) -> Seq a -> Seq a+dropWhile :: (a -> Bool) -> Seq a -> Seq a+splitWhile :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+zip :: Seq a -> Seq b -> Seq (a,b)+zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c)+zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c+zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d+unzip :: Seq (a,b) -> (Seq a, Seq b)+unzip3 :: Seq (a,b,c) -> (Seq a, Seq b, Seq c)+unzipWith :: (a -> b) -> (a -> c) -> Seq a -> (Seq b, Seq c)+unzipWith3 :: (a -> b) -> (a -> c) -> (a -> d) -> Seq a -> (Seq b, Seq c, Seq d)+strict :: Seq a -> Seq a+strictWith :: (a -> b) -> Seq a -> Seq a+structuralInvariant :: Seq a -> Bool++moduleName = "Data.Edison.Seq.JoinList"++data Seq a = E | L a | A (Seq a) (Seq a)+ -- invariant: E never a child of A++half :: Int -> Int+half n = n `div` 2++empty = E+singleton = L++lcons x E = L x+lcons x xs = A (L x) xs++rcons x E = L x+rcons x xs = A xs (L x)++append E ys = ys+append xs E = xs+append xs ys = A xs ys+++-- path reversal on lview/ltail++lview E = fail "JoinList.lview: empty sequence"+lview (L x) = return (x, E)+lview (A xs ys) = lvw xs ys+ where lvw E zs = error "JoinList.lvw: bug"+ lvw (L x) zs = return (x, zs)+ lvw (A xs ys) zs = lvw xs (A ys zs)++lhead E = error "JoinList.lhead: empty sequence"+lhead (L x) = x+lhead (A xs ys) = lhead xs++lheadM E = fail "JoinList.lheadM: empty sequence"+lheadM (L x) = return x+lheadM (A xs ys) = lheadM xs++ltail E = error "JoinList.ltail: empty sequence"+ltail (L x) = E+ltail (A xs ys) = ltl xs ys+ where ltl E zs = error "JoinList.ltl: bug"+ ltl (L x) zs = zs+ ltl (A xs ys) zs = ltl xs (A ys zs)++ltailM E = fail "JoinList.ltailM: empty sequence"+ltailM (L x) = return E+ltailM (A xs ys) = return (ltl xs ys)+ where ltl E zs = error "JoinList.ltl: bug"+ ltl (L x) zs = zs+ ltl (A xs ys) zs = ltl xs (A ys zs)+++-- Don't want to do plain path reversal on rview/rtail because of expectation+-- that left accesses are more common, so we would prefer to keep the left+-- spine short.++rview E = fail "JoinLis.rview: empty sequence"+rview (L x) = return (x, E)+rview (A xs ys) = rvw xs ys+ where rvw xs (A ys (A zs s)) = rvw (A xs (A ys zs)) s+ rvw xs (A ys (L x)) = return (x, A xs ys)+ rvw xs (L x) = return (x, xs)+ rvw xs _ = error "JoinList.rvw: bug"+ +rhead E = error "JoinList.rhead: empty sequence"+rhead (L x) = x+rhead (A xs ys) = rhead ys++rheadM E = fail "JoinList.rheadM: empty sequence"+rheadM (L x) = return x+rheadM (A xs ys) = rheadM ys++rtail E = error "JoinList.rtail: empty sequence"+rtail (L x) = E+rtail (A xs ys) = rtl xs ys+ where rtl xs (A ys (A zs s)) = A (A xs ys) (rtl zs s)+ rtl xs (A ys (L _)) = A xs ys+ rtl xs (L x) = xs+ rtl xs _ = error "JoinList.rtl: bug"++rtailM E = fail "JoinList.rtailM: empty sequence"+rtailM (L x) = return E+rtailM (A xs ys) = return (rtl xs ys)+ where rtl xs (A ys (A zs s)) = A (A xs ys) (rtl zs s)+ rtl xs (A ys (L _)) = A xs ys+ rtl xs (L x) = xs+ rtl xs _ = error "JoinList.rtl: bug"++null E = True+null _ = False++size xs = sz xs (0::Int)+ where sz E n = n+ sz (L x) n = n + (1::Int)+ sz (A xs ys) n = sz xs (sz ys n)++reverse (A xs ys) = A (reverse ys) (reverse xs)+reverse xs = xs -- L x or E++toList xs = tol xs []+ where tol E rest = rest+ tol (L x) rest = x:rest+ tol (A xs ys) rest = tol xs (tol ys rest)++map f E = E+map f (L x) = L (f x)+map f (A xs ys) = A (map f xs) (map f ys)++fold = foldr+fold' = foldr'+fold1 = fold1UsingFold+fold1' = fold1'UsingFold'++foldr f e E = e+foldr f e (L x) = f x e+foldr f e (A xs ys) = foldr f (foldr f e ys) xs++foldr' f e E = e+foldr' f e (L x) = f x $! e+foldr' f e (A xs ys) = (foldr' f $! (foldr' f e ys)) xs++foldl f e E = e+foldl f e (L x) = f e x+foldl f e (A xs ys) = foldl f (foldl f e xs) ys++foldl' f e E = e+foldl' f e (L x) = e `seq` f e x+foldl' f e (A xs ys) = e `seq` foldl' f (foldl' f e xs) ys++foldr1 f E = error "JoinList.foldr1: empty sequence"+foldr1 f (L x) = x+foldr1 f (A xs ys) = foldr f (foldr1 f ys) xs++foldr1' f E = error "JoinLis.foldr1': empty sequence"+foldr1' f (L x) = x+foldr1' f (A xs ys) = foldr' f (foldr1' f ys) xs++foldl1 f E = error "JoinList.foldl1: empty sequence"+foldl1 f (L x) = x+foldl1 f (A xs ys) = foldl f (foldl1 f xs) ys++foldl1' f E = error "JoinList.foldl1': empty sequence"+foldl1' f (L x) = x+foldl1' f (A xs ys) = foldl' f (foldl1' f xs) ys++copy n x + | n <= 0 = E+ | otherwise = cpy n x+ where cpy n x -- n > 0+ | even n = let xs = cpy (half n) x+ in A xs xs+ | n == 1 = L x+ | otherwise = let xs = cpy (half n) x+ in A (L x) (A xs xs)+++strict s@E = s+strict s@(L x) = s+strict s@(A l r) = strict l `seq` strict r `seq` s++strictWith f s@E = s+strictWith f s@(L x) = f x `seq` s+strictWith f s@(A l r) = strictWith f l `seq` strictWith f l `seq` s++-- invariants:+-- * 'E' is never a child of 'A'++structuralInvariant E = True+structuralInvariant s = check s+ where check E = False+ check (L _) = True+ check (A s1 s2) = check s1 && check s2+++concat = concatUsingFoldr+reverseOnto = reverseOntoUsingReverse+fromList = fromListUsingCons+concatMap = concatMapUsingFoldr++reducer = reducerUsingReduce1+reducer' = reducer'UsingReduce1'+reducel = reducelUsingReduce1+reducel' = reducel'UsingReduce1'+reduce1 = reduce1UsingLists+reduce1' = reduce1'UsingLists++inBounds = inBoundsUsingDrop+lookup = lookupUsingDrop+lookupM = lookupMUsingDrop+lookupWithDefault = lookupWithDefaultUsingDrop++update = updateUsingSplitAt+adjust = adjustUsingSplitAt++mapWithIndex = mapWithIndexUsingLists+foldrWithIndex = foldrWithIndexUsingLists+foldrWithIndex' = foldrWithIndex'UsingLists+foldlWithIndex = foldlWithIndexUsingLists+foldlWithIndex' = foldlWithIndex'UsingLists++take = takeUsingLview+drop = dropUsingLtail+splitAt = splitAtUsingLview+subseq = subseqDefault+ +filter = filterUsingLview+partition = partitionUsingFoldr+takeWhile = takeWhileUsingLview+dropWhile = dropWhileUsingLview+splitWhile = splitWhileUsingLview++zip = zipUsingLview+zip3 = zip3UsingLview+zipWith = zipWithUsingLview+zipWith3 = zipWith3UsingLview++unzip = unzipUsingFoldr+unzip3 = unzip3UsingFoldr+unzipWith = unzipWithUsingFoldr+unzipWith3 = unzipWith3UsingFoldr++-- instances++instance S.Sequence Seq where+ {lcons = lcons; rcons = rcons;+ lview = lview; lhead = lhead; ltail = ltail;+ lheadM = lheadM; ltailM = ltailM; rheadM = rheadM; rtailM = rtailM;+ rview = rview; rhead = rhead; rtail = rtail; null = null;+ 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; reducer' = reducer'; reducel = reducel;+ reducel' = reducel'; reduce1 = reduce1; reduce1' = reduce1';+ copy = copy; inBounds = inBounds; lookup = lookup;+ lookupM = lookupM; lookupWithDefault = lookupWithDefault;+ update = update; adjust = adjust; mapWithIndex = mapWithIndex;+ foldrWithIndex = foldrWithIndex; foldlWithIndex = foldlWithIndex;+ foldrWithIndex' = foldrWithIndex'; 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}++instance Functor Seq where+ fmap = map++instance Monad Seq where+ return = singleton+ xs >>= k = concatMap k xs++instance MonadPlus Seq where+ mplus = append+ mzero = empty++instance Eq a => Eq (Seq a) where+ xs == ys = toList xs == toList ys++instance Ord a => Ord (Seq a) where+ compare = defaultCompare++instance Show a => Show (Seq a) where+ showsPrec = showsPrecUsingToList++instance Read a => Read (Seq a) where+ readsPrec = readsPrecUsingFromList++instance Arbitrary a => Arbitrary (Seq a) where+ arbitrary = sized arbTree+ where arbTree 0 = return E+ arbTree 1 = liftM L arbitrary+ arbTree n =+ frequency [(1, liftM L arbitrary),+ (4, liftM2 A (arbTree (n `div` 2))+ (arbTree (n `div` 2)))]++ coarbitrary E = variant 0+ coarbitrary (L x) = variant 1 . coarbitrary x+ coarbitrary (A xs ys) = variant 2 . coarbitrary xs . coarbitrary ys++instance Monoid (Seq a) where+ mempty = empty+ mappend = append
+ src/Data/Edison/Seq/MyersStack.hs view
@@ -0,0 +1,438 @@+-- |+-- Module : Data.Edison.Seq.MyersStack+-- 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)+--+-- Meyers Stacks. All operations are as listed in "Data.Edison.Seq" except+-- the following:+--+-- * lookup, inBounds, drop @O( min(i, log n) )@+--+-- * rhead*, size @O( log n )@+--+-- * subseq @O( min (i, log n) + len )@+--+-- /References:/+--+-- * Eugene Myers. \"An applicative random-access stack\". /Information+-- Processing Letters/, 17(5):241-248, December 1983.++module Data.Edison.Seq.MyersStack (+ -- * Sequence Type+ Seq, -- instance of Sequence, Functor, Monad, MonadPlus++ -- * Sequence Operations+ empty,singleton,lcons,rcons,append,lview,lhead,ltail,rview,rhead,rtail,+ lheadM,ltailM,rheadM,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 Data.Edison.Prelude+import qualified Data.Edison.Seq as S ( Sequence(..) )+import Data.Edison.Seq.Defaults+import Control.Monad+import Control.Monad.Identity+import Data.Monoid+import Test.QuickCheck++-- signatures for exported functions+moduleName :: String+empty :: Seq a+singleton :: a -> Seq a+lcons :: a -> Seq a -> Seq a+rcons :: a -> Seq a -> Seq a+append :: Seq a -> Seq a -> Seq a+lview :: (Monad m) => Seq a -> m (a, Seq a)+lhead :: Seq a -> a+lheadM :: (Monad m) => Seq a -> m a+ltail :: Seq a -> Seq a+ltailM :: (Monad m) => Seq a -> m (Seq a)+rview :: (Monad m) => Seq a -> m (a, Seq a)+rhead :: Seq a -> a+rheadM :: (Monad m) => Seq a -> m a+rtail :: Seq a -> Seq a+rtailM :: (Monad m) => Seq a -> m (Seq a)+null :: Seq a -> Bool+size :: Seq a -> Int+concat :: Seq (Seq a) -> Seq a+reverse :: Seq a -> Seq a+reverseOnto :: Seq a -> Seq a -> Seq a+fromList :: [a] -> Seq a+toList :: Seq a -> [a]+map :: (a -> b) -> Seq a -> Seq b+concatMap :: (a -> Seq b) -> Seq a -> Seq b+fold :: (a -> b -> b) -> b -> Seq a -> b+fold' :: (a -> b -> b) -> b -> Seq a -> b+fold1 :: (a -> a -> a) -> Seq a -> a+fold1' :: (a -> a -> a) -> Seq a -> a+foldr :: (a -> b -> b) -> b -> Seq a -> b+foldl :: (b -> a -> b) -> b -> Seq a -> b+foldr1 :: (a -> a -> a) -> Seq a -> a+foldl1 :: (a -> a -> a) -> Seq a -> a+reducer :: (a -> a -> a) -> a -> Seq a -> a+reducel :: (a -> a -> a) -> a -> Seq a -> a+reduce1 :: (a -> a -> a) -> Seq a -> a+foldr' :: (a -> b -> b) -> b -> Seq a -> b+foldl' :: (b -> a -> b) -> b -> Seq a -> b+foldr1' :: (a -> a -> a) -> Seq a -> a+foldl1' :: (a -> a -> a) -> Seq a -> a+reducer' :: (a -> a -> a) -> a -> Seq a -> a+reducel' :: (a -> a -> a) -> a -> Seq a -> a+reduce1' :: (a -> a -> a) -> Seq a -> a+copy :: Int -> a -> Seq a+inBounds :: Int -> Seq a -> Bool+lookup :: Int -> Seq a -> a+lookupM :: (Monad m) => Int -> Seq a -> m a+lookupWithDefault :: a -> Int -> Seq a -> a+update :: Int -> a -> Seq a -> Seq a+adjust :: (a -> a) -> Int -> Seq a -> Seq a+mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b+foldrWithIndex :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex :: (b -> Int -> a -> b) -> b -> Seq a -> b+foldrWithIndex' :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex' :: (b -> Int -> a -> b) -> b -> Seq a -> b+take :: Int -> Seq a -> Seq a+drop :: Int -> Seq a -> Seq a+splitAt :: Int -> Seq a -> (Seq a, Seq a)+subseq :: Int -> Int -> Seq a -> Seq a+filter :: (a -> Bool) -> Seq a -> Seq a+partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+takeWhile :: (a -> Bool) -> Seq a -> Seq a+dropWhile :: (a -> Bool) -> Seq a -> Seq a+splitWhile :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+zip :: Seq a -> Seq b -> Seq (a,b)+zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c)+zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c+zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d+unzip :: Seq (a,b) -> (Seq a, Seq b)+unzip3 :: Seq (a,b,c) -> (Seq a, Seq b, Seq c)+unzipWith :: (a -> b) -> (a -> c) -> Seq a -> (Seq b, Seq c)+unzipWith3 :: (a -> b) -> (a -> c) -> (a -> d) -> Seq a -> (Seq b, Seq c, Seq d)+strict :: Seq a -> Seq a+strictWith :: (a -> b) -> Seq a -> Seq a+structuralInvariant :: Seq a -> Bool++moduleName = "Data.Edison.Seq.MyersStack"+++data Seq a = E | C !Int a (Seq a) (Seq a)+ -- what about strictness flags on tail and jump-tail?++-- auxiliary function+jump (C _ _ _ (C _ _ _ xs')) = xs'+jump _ = error "MyersStack.jump: bug!"++empty = E+singleton x = C 1 x E E++lcons x xs@(C i _ _ (C j _ _ xs'))+ | i == j = C (1 + i + j) x xs xs'+lcons x xs = C 1 x xs xs++lview E = fail "MyersStack.lview: empty sequence"+lview (C _ x xs _) = return (x, xs)++lhead E = error "MyersStack.lhead: empty sequence"+lhead (C _ x xs _) = x++lheadM E = fail "MyersStack.lheadM: empty sequence"+lheadM (C _ x xs _) = return x++ltail E = error "MyersStack.ltail: empty sequence"+ltail (C _ x xs _) = xs++ltailM E = fail "MyersStack.ltailM: empty sequence"+ltailM (C _ x xs _) = return xs++rview E = fail "MyersStack.rview: empty sequence"+rview xs = return (rhead xs, rtail xs)++rhead E = error "MyersStack.rhead: empty sequence"+rhead (C _ x xs xs') = rh x xs xs'+ where rh x xs (C _ y ys ys') = rh y ys ys'+ rh x (C _ y ys ys') E = rh y ys ys'+ rh x E E = x++rheadM E = fail "MyersStack.rheadM: empty sequence"+rheadM (C _ x xs xs') = return (rh x xs xs')+ where rh x xs (C _ y ys ys') = rh y ys ys'+ rh x (C _ y ys ys') E = rh y ys ys'+ rh x E E = x++rtail E = error "MyersStack.rtail: empty sequence"+rtail (C _ x xs _) = rt x xs+ where rt y E = E+ rt y (C _ x xs _) = lcons y (rt x xs)++rtailM E = fail "MyersStack.rtailM: empty sequence"+rtailM (C _ x xs _) = return (rt x xs)+ where rt y E = E+ rt y (C _ x xs _) = lcons y (rt x xs)++null E = True+null _ = False++size xs = go xs+ where go E = (0::Int)+ go (C j x xs xs') = j + size xs'++reverseOnto E ys = ys+reverseOnto (C _ x xs _) ys = reverseOnto xs (lcons x ys)++map f E = E+map f (C j x xs xs')+ | j == 1 = C j (f x) ys ys+ | otherwise = C j (f x) ys (jump ys)+ where ys = map f xs++fold = foldr+fold' f = foldl' (flip f)+fold1 = fold1UsingFold+fold1' = fold1'UsingFold'++foldr f e E = e+foldr f e (C _ x xs _) = f x (foldr f e xs)++foldr' f e E = e+foldr' f e (C _ x xs _) = f x $! (foldr' f e xs)++foldl f e E = e+foldl f e (C _ x xs _) = foldl f (f e x) xs++foldl' f e E = e+foldl' f e (C _ x xs _) = e `seq` foldl' f (f e x) xs++foldr1 f E = error "MyersStack.foldr1: empty sequence"+foldr1 f (C _ x xs _) = fr x xs+ where fr y E = y+ fr y (C _ x xs _) = f y (fr x xs)++foldr1' f E = error "MyersStack.foldr1': empty sequence"+foldr1' f (C _ x xs _) = fr x xs+ where fr y E = y+ fr y (C _ x xs _) = f y $! (fr x xs)++foldl1 f E = error "MyersStack.foldl1: empty sequence"+foldl1 f (C _ x xs _) = foldl f x xs++foldl1' f E = error "MyersStack.foldl1': empty sequence"+foldl1' f (C _ x xs _ ) = foldl' f x xs++inBounds i xs = inb xs i+ where inb E i = False+ inb (C j x xs xs') i+ | i < j = (i >= 0)+ | otherwise = inb xs' (i - j)++lookup i xs = runIdentity (lookupM i xs)++lookupM i xs = look xs i+ where look E i = fail "MyersStack.lookup: bad subscript"+ look (C j x xs xs') i+ | i >= j = look xs' (i - j)+ | i > 0 = look xs (i - 1)+ | i == 0 = return x+ | otherwise = nothing+ nothing = fail "MyersStack.lookup: not found"++lookupWithDefault d i xs = look xs i+ where look E i = d+ look (C j x xs xs') i+ | i >= j = look xs' (i - j)+ | i > 0 = look xs (i - 1)+ | i == 0 = x+ | otherwise = d++update i y xs = upd i xs+ where upd i E = E+ upd 0 (C j x xs xs') = C j y xs xs'+ upd i (C j x xs _)+ | j == 1 = C j x ys ys+ | otherwise = C j x ys (jump ys)+ where ys = upd (i - 1) xs++adjust f i xs = adj i xs+ where adj i E = E+ adj 0 (C j x xs xs') = C j (f x) xs xs'+ adj i (C j x xs _)+ | j == 1 = C j x ys ys+ | otherwise = C j x ys (jump ys)+ where ys = adj (i - (1::Int)) xs++drop n xs = drp n xs+ where drp n xs | n <= 0 = xs+ drp n E = E+ drp n (C j x xs xs')+ | n < j = drp (n - 1) xs+ | otherwise = drp (n - j) xs'++unzip E = (E, E)+unzip (C j (x,y) ps ps')+ | j == 1 = (C j x xs xs, C j y ys ys)+ | otherwise = (C j x xs (jump xs), C j y ys (jump ys))+ where (xs,ys) = unzip ps++unzip3 E = (E, E, E)+unzip3 (C j (x,y,z) ts ts')+ | j == 1 = (C j x xs xs, C j y ys ys, C j z zs zs)+ | otherwise = (C j x xs (jump xs), C j y ys (jump ys), C j z zs (jump zs))+ where (xs,ys,zs) = unzip3 ts++unzipWith f g E = (E, E)+unzipWith f g (C j x xs _)+ | j == 1 = (C j (f x) as as, C j (g x) bs bs)+ | otherwise = (C j (f x) as (jump as), C j (g x) bs (jump bs))+ where (as,bs) = unzipWith f g xs++unzipWith3 f g h E = (E, E, E)+unzipWith3 f g h (C j x xs _)+ | j == 1 = (C j (f x) as as, C j (g x) bs bs, C j (h x) cs cs)+ | otherwise = (C j (f x) as (jump as), C j (g x) bs (jump bs),+ C j (h x) cs (jump cs))+ where (as,bs,cs) = unzipWith3 f g h xs++strict s@E = s+strict s@(C i x xs _) = strict xs `seq` s++strictWith f s@E = s+strictWith f s@(C i x xs _) = f x `seq` strictWith f xs `seq` s++-- the remaining functions all use defaults++rcons = rconsUsingFoldr+append = appendUsingFoldr+concat = concatUsingFoldr+reverse = reverseUsingReverseOnto+fromList = fromListUsingCons+toList = toListUsingFoldr+concatMap = concatMapUsingFoldr+reducer = reducerUsingReduce1+reducer' = reducer'UsingReduce1'+reducel = reducelUsingReduce1+reducel' = reducel'UsingReduce1'+reduce1 = reduce1UsingLists+reduce1' = reduce1'UsingLists+copy = copyUsingLists+mapWithIndex = mapWithIndexUsingLists+foldrWithIndex = foldrWithIndexUsingLists+foldrWithIndex' = foldrWithIndex'UsingLists+foldlWithIndex = foldlWithIndexUsingLists+foldlWithIndex' = foldlWithIndex'UsingLists+take = takeUsingLists+splitAt = splitAtDefault+filter = filterUsingFoldr+partition = partitionUsingFoldr+subseq = subseqDefault+takeWhile = takeWhileUsingLview+dropWhile = dropWhileUsingLview+splitWhile = splitWhileUsingLview++-- for zips, could optimize by calculating which one is shorter and+-- retaining its shape++zip = zipUsingLists+zip3 = zip3UsingLists+zipWith = zipWithUsingLists+zipWith3 = zipWith3UsingLists++-- FIXME what are the structural invariants?+structuralInvariant = const True++-- instances++instance S.Sequence Seq where+ {lcons = lcons; rcons = rcons;+ lview = lview; lhead = lhead; ltail = ltail;+ lheadM = lheadM; ltailM = ltailM; rheadM = rheadM; rtailM = rtailM;+ rview = rview; rhead = rhead; rtail = rtail; null = null;+ 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; reducer' = reducer'; reducel = reducel;+ reducel' = reducel'; reduce1 = reduce1; 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}++instance Functor Seq where+ fmap = map++instance Monad Seq where+ return = singleton+ xs >>= k = concatMap k xs++instance MonadPlus Seq where+ mplus = append+ mzero = empty++instance Eq a => Eq (Seq a) where+ xs == ys =+ (size xs == size ys) && (toList xs == toList ys)++instance Ord a => Ord (Seq a) where+ compare = defaultCompare++instance Show a => Show (Seq a) where+ showsPrec = showsPrecUsingToList++instance Read a => Read (Seq a) where+ readsPrec = readsPrecUsingFromList+++instance Arbitrary a => Arbitrary (Seq a) where+ arbitrary = do xs <- arbitrary+ return (fromList xs)++ coarbitrary xs = coarbitrary (toList xs)++instance Monoid (Seq a) where+ mempty = empty+ mappend = append+++-------------++{-+questions:+ - any benefit to+ E | C1 x xs | CJ Int# x xs xs'++ - any benefit to length instead of delta?++ - any benefit to delta not counting x (i.e., base 0 instead of base 1)?++I don't believe any will do any better, except possibly the first+-}+
+ src/Data/Edison/Seq/RandList.hs view
@@ -0,0 +1,481 @@+-- |+-- Module : Data.Edison.Seq.RandList+-- 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)+--+-- Random-Access Lists. All operations are as listed in "Data.Edison.Seq"+-- except the following:+--+-- * rhead*, size @O( log n )@+--+-- * copy, inBounds @O( log i )@+--+-- * lookup*, update, adjust, drop @O( min( i, log n ) )@+--+-- * subseq @O( min( i, log n ) + len )@+--+-- /References:/+--+-- * Chris Okasaki. /Purely Functional Data Structures/. 1998.+-- Section 9.3.1.+--+-- * Chris Okasaki. \"Purely Functional Random Access Lists\". FPCA'95,+-- pages 86-95.++module Data.Edison.Seq.RandList (+ -- * Sequence Type+ Seq, -- instance of Sequence, Functor, Monad, MonadPlus++ -- * Sequence Operations+ empty,singleton,lcons,rcons,append,lview,lhead,ltail,rview,rhead,rtail,+ lheadM,ltailM,rheadM,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 Data.Edison.Prelude+import qualified Data.Edison.Seq as S( Sequence(..) )+import Data.Edison.Seq.Defaults+import Control.Monad+import Control.Monad.Identity+import Data.Monoid+import Test.QuickCheck++-- signatures for exported functions+moduleName :: String+empty :: Seq a+singleton :: a -> Seq a+lcons :: a -> Seq a -> Seq a+rcons :: a -> Seq a -> Seq a+append :: Seq a -> Seq a -> Seq a+lview :: (Monad m) => Seq a -> m (a, Seq a)+lhead :: Seq a -> a+lheadM :: (Monad m) => Seq a -> m a+ltail :: Seq a -> Seq a+ltailM :: (Monad m) => Seq a -> m (Seq a)+rview :: (Monad m) => Seq a -> m (a, Seq a)+rhead :: Seq a -> a+rheadM :: (Monad m) => Seq a -> m a+rtail :: Seq a -> Seq a+rtailM :: (Monad m) => Seq a -> m (Seq a)+null :: Seq a -> Bool+size :: Seq a -> Int+concat :: Seq (Seq a) -> Seq a+reverse :: Seq a -> Seq a+reverseOnto :: Seq a -> Seq a -> Seq a+fromList :: [a] -> Seq a+toList :: Seq a -> [a]+map :: (a -> b) -> Seq a -> Seq b+concatMap :: (a -> Seq b) -> Seq a -> Seq b+fold :: (a -> b -> b) -> b -> Seq a -> b+fold' :: (a -> b -> b) -> b -> Seq a -> b+fold1 :: (a -> a -> a) -> Seq a -> a+fold1' :: (a -> a -> a) -> Seq a -> a+foldr :: (a -> b -> b) -> b -> Seq a -> b+foldl :: (b -> a -> b) -> b -> Seq a -> b+foldr1 :: (a -> a -> a) -> Seq a -> a+foldl1 :: (a -> a -> a) -> Seq a -> a+reducer :: (a -> a -> a) -> a -> Seq a -> a+reducel :: (a -> a -> a) -> a -> Seq a -> a+reduce1 :: (a -> a -> a) -> Seq a -> a+foldr' :: (a -> b -> b) -> b -> Seq a -> b+foldl' :: (b -> a -> b) -> b -> Seq a -> b+foldr1' :: (a -> a -> a) -> Seq a -> a+foldl1' :: (a -> a -> a) -> Seq a -> a+reducer' :: (a -> a -> a) -> a -> Seq a -> a+reducel' :: (a -> a -> a) -> a -> Seq a -> a+reduce1' :: (a -> a -> a) -> Seq a -> a+copy :: Int -> a -> Seq a+inBounds :: Int -> Seq a -> Bool+lookup :: Int -> Seq a -> a+lookupM :: (Monad m) => Int -> Seq a -> m a+lookupWithDefault :: a -> Int -> Seq a -> a+update :: Int -> a -> Seq a -> Seq a+adjust :: (a -> a) -> Int -> Seq a -> Seq a+mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b+foldrWithIndex :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex :: (b -> Int -> a -> b) -> b -> Seq a -> b+foldrWithIndex' :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex' :: (b -> Int -> a -> b) -> b -> Seq a -> b+take :: Int -> Seq a -> Seq a+drop :: Int -> Seq a -> Seq a+splitAt :: Int -> Seq a -> (Seq a, Seq a)+subseq :: Int -> Int -> Seq a -> Seq a+filter :: (a -> Bool) -> Seq a -> Seq a+partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+takeWhile :: (a -> Bool) -> Seq a -> Seq a+dropWhile :: (a -> Bool) -> Seq a -> Seq a+splitWhile :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+zip :: Seq a -> Seq b -> Seq (a,b)+zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c)+zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c+zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d+unzip :: Seq (a,b) -> (Seq a, Seq b)+unzip3 :: Seq (a,b,c) -> (Seq a, Seq b, Seq c)+unzipWith :: (a -> b) -> (a -> c) -> Seq a -> (Seq b, Seq c)+unzipWith3 :: (a -> b) -> (a -> c) -> (a -> d) -> Seq a -> (Seq b, Seq c, Seq d)+strict :: Seq a -> Seq a+strictWith :: (a -> b) -> Seq a -> Seq a+moduleName = "Data.Edison.Seq.RandList"+++data Tree a = L a | T a (Tree a) (Tree a) deriving (Eq)+data Seq a = E | C !Int (Tree a) (Seq a) deriving (Eq)++half :: Int -> Int+half n = n `quot` 2 -- use a shift?++empty = E+singleton x = C 1 (L x) E++lcons x xs@(C i s (C j t xs'))+ | i == j = C (1 + i + j) (T x s t) xs'+lcons x xs = C 1 (L x) xs++copy n x = if n <= 0 then E else buildTrees (1::Int) (L x)+ where buildTrees j t+ | j > n = takeTrees n (half j) (child t) E+ | otherwise = buildTrees (1 + j + j) (T x t t)++ takeTrees i j t xs+ | i >= j = takeTrees (i - j) j t (C j t xs)+ | i > 0 = takeTrees i (half j) (child t) xs+ | otherwise = xs++ child (T x s t) = t+ child _ = error "RandList.copy: bug!"++lview E = fail "RandList.lview: empty sequence"+lview (C _ (L x) xs) = return (x, xs)+lview (C i (T x s t) xs) = return (x, C j s (C j t xs))+ where j = half i++lhead E = error "RandList.lhead: empty sequence"+lhead (C _ (L x) xs) = x+lhead (C _ (T x s t) xs) = x++lheadM E = fail "RandList.lheadM: empty sequence"+lheadM (C _ (L x) xs) = return x+lheadM (C _ (T x s t) xs) = return x++ltail E = error "RandList.ltail: empty sequence"+ltail (C _ (L x) xs) = xs+ltail (C i (T x s t) xs) = C j s (C j t xs)+ where j = half i++ltailM E = fail "RandList.ltailM: empty sequence"+ltailM (C _ (L x) xs) = return xs+ltailM (C i (T x s t) xs) = return (C j s (C j t xs))+ where j = half i++rhead E = error "RandList.rhead: empty sequence"+rhead (C _ t E) = treeLast t+ where treeLast (L x) = x+ treeLast (T x s t) = treeLast t+rhead (C _ t xs) = rhead xs++rheadM E = fail "RandList.rhead: empty sequence"+rheadM (C _ t E) = return(treeLast t)+ where treeLast (L x) = x+ treeLast (T x s t) = treeLast t+rheadM (C _ t xs) = rheadM xs+++null E = True+null _ = False++size xs = sz xs+ where sz E = (0::Int)+ sz (C j t xs) = j + sz xs++reverseOnto E ys = ys+reverseOnto (C _ t xs) ys = reverseOnto xs (revTree t ys)+ where revTree (L x) ys = lcons x ys+ revTree (T x s t) ys = revTree t (revTree s (lcons x ys))++map f E = E+map f (C j t xs) = C j (mapTree f t) (map f xs)+ where mapTree f (L x) = L (f x)+ mapTree f (T x s t) = T (f x) (mapTree f s) (mapTree f t)++fold = foldr+fold' f = foldl' (flip f)+fold1 = fold1UsingFold+fold1' = fold1'UsingFold'++foldr f e E = e+foldr f e (C _ t xs) = foldTree t (foldr f e xs)+ where foldTree (L x) e = f x e+ foldTree (T x s t) e = f x (foldTree s (foldTree t e))++foldr' f e E = e+foldr' f e (C _ t xs) = foldTree t $! (foldr' f e xs)+ where foldTree (L x) e = f x $! e+ foldTree (T x s t) e = f x $! (foldTree s $! (foldTree t $! e))++foldl f e E = e+foldl f e (C _ t xs) = foldl f (foldTree e t) xs+ where foldTree e (L x) = f e x+ foldTree e (T x s t) = foldTree (foldTree (f e x) s) t++foldl' f e E = e+foldl' f e (C _ t xs) = (foldl f $! (foldTree e t)) xs+ where foldTree e (L x) = e `seq` f e x+ foldTree e (T x s t) = e `seq` (foldTree $! (foldTree (f e x) s)) t++reduce1 f xs = case lview xs of+ Nothing -> error "RandList.reduce1: empty seq"+ Just (x, xs) -> red1 x xs+ where red1 x E = x+ red1 x (C j t xs) = red1 (redTree x t) xs++ redTree x (L y) = f x y+ redTree x (T y s t) = redTree (redTree (f x y) s) t++reduce1' f xs = case lview xs of+ Nothing -> error "RandList.reduce1': empty seq"+ Just (x, xs) -> red1 x xs+ where red1 x E = x+ red1 x (C j t xs) = (red1 $! (redTree x t)) xs++ redTree x (L y) = x `seq` y `seq` f x y+ redTree x (T y s t) = x `seq` y `seq` (redTree $! (redTree (f x y) s)) t+++inBounds i xs = inb xs i+ where inb E i = False+ inb (C j t xs) i+ | i < j = (i >= 0)+ | otherwise = inb xs (i - j)++lookup i xs = runIdentity (lookupM i xs)++lookupM i xs = look xs i+ where look E i = fail "RandList.lookup bad subscript"+ look (C j t xs) i+ | i < j = lookTree j t i+ | otherwise = look xs (i - j)++ lookTree _ (L x) i+ | i == 0 = return x+ | otherwise = nothing+ lookTree j (T x s t) i+ | i > k = lookTree k t (i - 1 - k)+ | i /= 0 = lookTree k s (i - 1)+ | otherwise = return x+ where k = half j+ nothing = fail "RandList.lookup: not found"++lookupWithDefault d i xs = look xs i+ where look E i = d+ look (C j t xs) i+ | i < j = lookTree j t i+ | otherwise = look xs (i - j)++ lookTree _ (L x) i+ | i == 0 = x+ | otherwise = d+ lookTree j (T x s t) i+ | i > k = lookTree k t (i - 1 - k)+ | i /= 0 = lookTree k s (i - 1)+ | otherwise = x+ where k = half j++update i y xs = upd i xs+ where upd i E = E+ upd i (C j t xs)+ | i < j = C j (updTree i j t) xs+ | otherwise = C j t (upd (i - j) xs)++ updTree i j t@(L x)+ | i == 0 = L y+ | otherwise = t+ updTree i j (T x s t)+ | i > k = T x s (updTree (i - 1 - k) k t)+ | i /= 0 = T x (updTree (i - 1) k s) t+ | otherwise = T y s t+ where k = half j++adjust f i xs = adj i xs+ where adj i E = E+ adj i (C j t xs)+ | i < j = C j (adjTree i j t) xs+ | otherwise = C j t (adj (i - j) xs)++ adjTree i j t@(L x)+ | i == 0 = L (f x)+ | otherwise = t+ adjTree i j (T x s t)+ | i > k = T x s (adjTree (i - 1 - k) k t)+ | i /= 0 = T x (adjTree (i - 1) k s) t+ | otherwise = T (f x) s t+ where k = half j++drop n xs = if n < 0 then xs else drp n xs+ where drp i E = E+ drp i (C j t xs)+ | i < j = drpTree i j t xs+ | otherwise = drp (i - j) xs++ drpTree 0 j t xs = C j t xs+ drpTree i j (L x) xs = error "RandList.drop: bug. Impossible case!"+ drpTree i j (T x s t) xs+ | i > k = drpTree (i - 1 - k) k t xs+ | otherwise = drpTree (i - 1) k s (C k t xs)+ where k = half j++strict s@E = s+strict s@(C j t xs) = strictTree t `seq` strict xs `seq` s++strictTree t@(L x) = t+strictTree t@(T x l r) = strictTree l `seq` strictTree r `seq` t++strictWith f s@E = s+strictWith f s@(C j t xs) = strictWithTree f t `seq` strictWith f xs `seq` s++strictWithTree f t@(L x) = f x `seq` t+strictWithTree f t@(T x l r) = f x `seq` strictWithTree f l `seq` strictWithTree f r `seq` t+++-- the remaining functions all use defaults++rcons = rconsUsingFoldr+append = appendUsingFoldr+rview = rviewDefault+rtail = rtailUsingLview+rtailM = rtailMUsingLview+concat = concatUsingFoldr+reverse = reverseUsingReverseOnto+fromList = fromListUsingCons+toList = toListUsingFoldr+concatMap = concatMapUsingFoldr+foldr1 = foldr1UsingLview+foldr1' = foldr1'UsingLview+foldl1 = foldl1UsingFoldl+foldl1' = foldl1'UsingFoldl'+reducer = reducerUsingReduce1+reducer' = reducer'UsingReduce1'+reducel = reducelUsingReduce1+reducel' = reducel'UsingReduce1'+mapWithIndex = mapWithIndexUsingLists+foldrWithIndex = foldrWithIndexUsingLists+foldrWithIndex' = foldrWithIndex'UsingLists+foldlWithIndex = foldlWithIndexUsingLists+foldlWithIndex' = foldlWithIndex'UsingLists+take = takeUsingLists+splitAt = splitAtDefault+filter = filterUsingFoldr+partition = partitionUsingFoldr+subseq = subseqDefault+takeWhile = takeWhileUsingLview+dropWhile = dropWhileUsingLview+splitWhile = splitWhileUsingLview++-- for zips, could optimize by calculating which one is shorter and+-- retaining its shape++zip = zipUsingLists+zip3 = zip3UsingLists+zipWith = zipWithUsingLists+zipWith3 = zipWith3UsingLists+unzip = unzipUsingLists+unzip3 = unzip3UsingLists+unzipWith = unzipWithUsingLists+unzipWith3 = unzipWith3UsingLists++-- invariants: +-- * list of complete binary trees in non-decreasing+-- order by size+-- * first argument to 'C' is the number+-- of nodes in the tree++structuralInvariant E = True+structuralInvariant (C x t s) = x > 0 && checkTree x t && checkSeq x s++ where checkTree 1 (L _) = True+ checkTree w (T _ l r) = + let w' = (w - 1) `div` 2 + in w' > 0 && checkTree w' l && checkTree w' r+ checkTree _ _ = False++ checkSeq x E = True+ checkSeq x (C y t s) = + x <= y && checkTree y t && checkSeq y s+++-- instances++instance S.Sequence Seq where+ {lcons = lcons; rcons = rcons;+ lview = lview; lhead = lhead; ltail = ltail;+ lheadM = lheadM; ltailM = ltailM; rheadM = rheadM; rtailM = rtailM;+ rview = rview; rhead = rhead; rtail = rtail; null = null;+ 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; reducer' = reducer'; reducel = reducel;+ reducel' = reducel'; reduce1 = reduce1; 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}++instance Functor Seq where+ fmap = map++instance Monad Seq where+ return = singleton+ xs >>= k = concatMap k xs++instance MonadPlus Seq where+ mplus = append+ mzero = empty++instance Ord a => Ord (Seq a) where+ compare = defaultCompare++instance Show a => Show (Seq a) where+ showsPrec = showsPrecUsingToList++instance Read a => Read (Seq a) where+ readsPrec = readsPrecUsingFromList++instance Arbitrary a => Arbitrary (Seq a) where+ arbitrary = do xs <- arbitrary+ return (fromList xs)++ coarbitrary xs = coarbitrary (toList xs)++instance Monoid (Seq a) where+ mempty = empty+ mappend = append
+ src/Data/Edison/Seq/RevSeq.hs view
@@ -0,0 +1,382 @@+-- |+-- Module : Data.Edison.Seq.RevSeq+-- 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)+--+-- This module defines a sequence adaptor @Rev s@.+-- If @s@ is a sequence type constructor, then @Rev s@+-- is a sequence type constructor that is identical to @s@,+-- except that it is kept in the opposite order.+-- Also keeps explicit track of the size of the sequence,+-- similar to the @Sized@ adaptor in "Data.Edison.Seq.SizedSeq".+--+-- This module is most useful when s is a sequence type+-- that offers fast access to the front but slow access+-- to the rear, and your application needs the opposite+-- (i.e., fast access to the rear but slow access to the+-- front).+--+-- All time complexities are determined by the underlying+-- sequence, except that the complexities for accessing+-- the left and right sides of the sequence are exchanged,+-- and size becomes @O( 1 )@.++module Data.Edison.Seq.RevSeq (+ -- * Rev Sequence Type+ Rev, -- Rev s instance of Sequence, Functor, Monad, MonadPlus++ -- * Sequence Operations+ empty,singleton,lcons,rcons,append,lview,lhead,ltail,rview,rhead,rtail,+ lheadM,ltailM,rheadM,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,instanceName,++ -- * Other supported operations+ fromSeq,toSeq++) 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 Data.Edison.Prelude+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Seq.ListSeq as L+import Data.Edison.Seq.Defaults -- only used by concatMap+import Control.Monad+import Data.Monoid+import Test.QuickCheck+++-- signatures for exported functions+moduleName :: String+instanceName :: S.Sequence s => Rev s a -> String+empty :: S.Sequence s => Rev s a+singleton :: S.Sequence s => a -> Rev s a+lcons :: S.Sequence s => a -> Rev s a -> Rev s a+rcons :: S.Sequence s => a -> Rev s a -> Rev s a+append :: S.Sequence s => Rev s a -> Rev s a -> Rev s a+lview :: (S.Sequence s, Monad m) => Rev s a -> m (a, Rev s a)+lhead :: S.Sequence s => Rev s a -> a+lheadM :: (S.Sequence s, Monad m) => Rev s a -> m a+ltail :: S.Sequence s => Rev s a -> Rev s a+ltailM :: (S.Sequence s, Monad m) => Rev s a -> m (Rev s a)+rview :: (S.Sequence s, Monad m) => Rev s a -> m (a, Rev s a)+rhead :: S.Sequence s => Rev s a -> a+rheadM :: (S.Sequence s, Monad m) => Rev s a -> m a+rtail :: S.Sequence s => Rev s a -> Rev s a+rtailM :: (S.Sequence s, Monad m) => Rev s a -> m (Rev s a)+null :: S.Sequence s => Rev s a -> Bool+size :: S.Sequence s => Rev s a -> Int+concat :: S.Sequence s => Rev s (Rev s a) -> Rev s a+reverse :: S.Sequence s => Rev s a -> Rev s a+reverseOnto :: S.Sequence s => Rev s a -> Rev s a -> Rev s a+fromList :: S.Sequence s => [a] -> Rev s a+toList :: S.Sequence s => Rev s a -> [a]+map :: S.Sequence s => (a -> b) -> Rev s a -> Rev s b+concatMap :: S.Sequence s => (a -> Rev s b) -> Rev s a -> Rev s b+fold :: S.Sequence s => (a -> b -> b) -> b -> Rev s a -> b+fold' :: S.Sequence s => (a -> b -> b) -> b -> Rev s a -> b+fold1 :: S.Sequence s => (a -> a -> a) -> Rev s a -> a+fold1' :: S.Sequence s => (a -> a -> a) -> Rev s a -> a+foldr :: S.Sequence s => (a -> b -> b) -> b -> Rev s a -> b+foldl :: S.Sequence s => (b -> a -> b) -> b -> Rev s a -> b+foldr1 :: S.Sequence s => (a -> a -> a) -> Rev s a -> a+foldl1 :: S.Sequence s => (a -> a -> a) -> Rev s a -> a+reducer :: S.Sequence s => (a -> a -> a) -> a -> Rev s a -> a+reducel :: S.Sequence s => (a -> a -> a) -> a -> Rev s a -> a+reduce1 :: S.Sequence s => (a -> a -> a) -> Rev s a -> a+foldr' :: S.Sequence s => (a -> b -> b) -> b -> Rev s a -> b+foldl' :: S.Sequence s => (b -> a -> b) -> b -> Rev s a -> b+foldr1' :: S.Sequence s => (a -> a -> a) -> Rev s a -> a+foldl1' :: S.Sequence s => (a -> a -> a) -> Rev s a -> a+reducer' :: S.Sequence s => (a -> a -> a) -> a -> Rev s a -> a+reducel' :: S.Sequence s => (a -> a -> a) -> a -> Rev s a -> a+reduce1' :: S.Sequence s => (a -> a -> a) -> Rev s a -> a+copy :: S.Sequence s => Int -> a -> Rev s a+inBounds :: S.Sequence s => Int -> Rev s a -> Bool+lookup :: S.Sequence s => Int -> Rev s a -> a+lookupM :: (S.Sequence s, Monad m) => Int -> Rev s a -> m a+lookupWithDefault :: S.Sequence s => a -> Int -> Rev s a -> a+update :: S.Sequence s => Int -> a -> Rev s a -> Rev s a+adjust :: S.Sequence s => (a -> a) -> Int -> Rev s a -> Rev s a+mapWithIndex :: S.Sequence s => (Int -> a -> b) -> Rev s a -> Rev s b+foldrWithIndex :: S.Sequence s => (Int -> a -> b -> b) -> b -> Rev s a -> b+foldlWithIndex :: S.Sequence s => (b -> Int -> a -> b) -> b -> Rev s a -> b+foldrWithIndex' :: S.Sequence s => (Int -> a -> b -> b) -> b -> Rev s a -> b+foldlWithIndex' :: S.Sequence s => (b -> Int -> a -> b) -> b -> Rev s a -> b+take :: S.Sequence s => Int -> Rev s a -> Rev s a+drop :: S.Sequence s => Int -> Rev s a -> Rev s a+splitAt :: S.Sequence s => Int -> Rev s a -> (Rev s a, Rev s a)+subseq :: S.Sequence s => Int -> Int -> Rev s a -> Rev s a+filter :: S.Sequence s => (a -> Bool) -> Rev s a -> Rev s a+partition :: S.Sequence s => (a -> Bool) -> Rev s a -> (Rev s a, Rev s a)+takeWhile :: S.Sequence s => (a -> Bool) -> Rev s a -> Rev s a+dropWhile :: S.Sequence s => (a -> Bool) -> Rev s a -> Rev s a+splitWhile :: S.Sequence s => (a -> Bool) -> Rev s a -> (Rev s a, Rev s a)+zip :: S.Sequence s => Rev s a -> Rev s b -> Rev s (a,b)+zip3 :: S.Sequence s => Rev s a -> Rev s b -> Rev s c -> Rev s (a,b,c)+zipWith :: S.Sequence s => (a -> b -> c) -> Rev s a -> Rev s b -> Rev s c+zipWith3 :: S.Sequence s => (a -> b -> c -> d) -> Rev s a -> Rev s b -> Rev s c -> Rev s d+unzip :: S.Sequence s => Rev s (a,b) -> (Rev s a, Rev s b)+unzip3 :: S.Sequence s => Rev s (a,b,c) -> (Rev s a, Rev s b, Rev s c)+unzipWith :: S.Sequence s => (a -> b) -> (a -> c) -> Rev s a -> (Rev s b, Rev s c)+unzipWith3 :: S.Sequence s => (a -> b) -> (a -> c) -> (a -> d) -> Rev s a -> (Rev s b, Rev s c, Rev s d)+strict :: S.Sequence s => Rev s a -> Rev s a+strictWith :: S.Sequence s => (a -> b) -> Rev s a -> Rev s a+structuralInvariant :: S.Sequence s => Rev s a -> Bool++-- bonus functions, not in Sequence signature+fromSeq :: S.Sequence s => s a -> Rev s a+toSeq :: S.Sequence s => Rev s a -> s a+++moduleName = "Data.Edison.Seq.RevSeq"+instanceName (N m s) = "RevSeq(" ++ S.instanceName s ++ ")"++data Rev s a = N !Int (s a)+ -- The Int is the size minus one. The "minus one" makes indexing+ -- calculations easier.++fromSeq xs = N (S.size xs - 1) xs+toSeq (N m xs) = xs++empty = N (-1) S.empty+singleton x = N 0 (S.singleton x)+lcons x (N m xs) = N (m+1) (S.rcons x xs)+rcons x (N m xs) = N (m+1) (S.lcons x xs)+append (N m xs) (N n ys) = N (m+n+1) (S.append ys xs)++lview (N m xs) = case S.rview xs of+ Nothing -> fail "RevSeq.lview: empty sequence"+ Just (x,xs) -> return (x, N (m-1) xs)++lhead (N m xs) = S.rhead xs++lheadM (N m xs) = S.rheadM xs++ltail (N (-1) xs) = error "RevSeq.ltail: empty sequence"+ltail (N m xs) = N (m-1) (S.rtail xs)++ltailM (N (-1) xs) = fail "RevSeq.ltailM: empty sequence"+ltailM (N m xs) = return (N (m-1) (S.rtail xs))++rview (N m xs) = case S.lview xs of+ Nothing -> fail "RevSeq.rview: empty sequence"+ Just (x,xs) -> return (x, N (m-1) xs)+ +rhead (N m xs) = S.lhead xs++rheadM (N m xs) = S.lheadM xs++rtail (N (-1) xs) = error "RevSeq.rtail: empty sequence"+rtail (N m xs) = N (m-1) (S.ltail xs)++rtailM (N (-1) xs) = fail "RevSeq.rtailM: empty sequence"+rtailM (N m xs) = return (N (m-1) (S.ltail xs))++null (N m xs) = m == -1+size (N m xs) = m+1+concat (N m xss) = fromSeq (S.concat (S.map toSeq xss))+reverse (N m xs) = N m (S.reverse xs)+reverseOnto (N m xs) (N n ys) = N (m+n+1) (S.append ys (S.reverse xs))+fromList = fromSeq . S.fromList . L.reverse+toList (N m xs) = S.foldl (flip (:)) [] xs+map f (N m xs) = N m (S.map f xs)++concatMap = concatMapUsingFoldr -- only function that uses a default++fold f e (N m xs) = S.fold f e xs+fold' f e (N m xs) = S.fold' f e xs+fold1 f (N m xs) = S.fold1 f xs+fold1' f (N m xs) = S.fold1' f xs+foldr f e (N m xs) = S.foldl (flip f) e xs+foldr' f e (N m xs) = S.foldl' (flip f) e xs+foldl f e (N m xs) = S.foldr (flip f) e xs+foldl' f e (N m xs) = S.foldr' (flip f) e xs+foldr1 f (N m xs) = S.foldl1 (flip f) xs+foldr1' f (N m xs) = S.foldl1' (flip f) xs+foldl1 f (N m xs) = S.foldr1 (flip f) xs+foldl1' f (N m xs) = S.foldr1' (flip f) xs+reducer f e (N m xs) = S.reducel (flip f) e xs+reducer' f e (N m xs) = S.reducel' (flip f) e xs+reducel f e (N m xs) = S.reducer (flip f) e xs+reducel' f e (N m xs) = S.reducer' (flip f) e xs+reduce1 f (N m xs) = S.reduce1 (flip f) xs+reduce1' f (N m xs) = S.reduce1' (flip f) xs++copy n x + | n <= 0 = empty+ | otherwise = N (n-1) (S.copy n x)++inBounds i (N m xs) = (i >= 0) && (i <= m)+lookup i (N m xs) = S.lookup (m-i) xs+lookupM i (N m xs) = S.lookupM (m-i) xs+lookupWithDefault d i (N m xs) = S.lookupWithDefault d (m-i) xs+update i x (N m xs) = N m (S.update (m-i) x xs)+adjust f i (N m xs) = N m (S.adjust f (m-i) xs)+mapWithIndex f (N m xs) = N m (S.mapWithIndex (f . (m-)) xs)++foldrWithIndex f e (N m xs) = S.foldlWithIndex f' e xs+ where f' xs i x = f (m-i) x xs+foldrWithIndex' f e (N m xs) = S.foldlWithIndex' f' e xs+ where f' xs i x = f (m-i) x xs++foldlWithIndex f e (N m xs) = S.foldrWithIndex f' e xs+ where f' i x xs = f xs (m-i) x+foldlWithIndex' f e (N m xs) = S.foldrWithIndex' f' e xs+ where f' i x xs = f xs (m-i) x++take i original@(N m xs)+ | i <= 0 = empty+ | i > m = original+ | otherwise = N (i-1) (S.drop (m-i+1) xs)++drop i original@(N m xs)+ | i <= 0 = original+ | i > m = empty+ | otherwise = N (m-i) (S.take (m-i+1) xs)++splitAt i original@(N m xs)+ | i <= 0 = (empty, original)+ | i > m = (original, empty)+ | otherwise = let (ys,zs) = S.splitAt (m-i+1) xs+ in (N (i-1) zs, N (m-i) ys)++subseq i len original@(N m xs)+ | i <= 0 = take len original+ | i > m || len <= 0 = empty+ | i+len > m = N (m-i) (S.take (m-i+1) xs)+ | otherwise = N (len-1) (S.subseq (m-i-len+1) len xs)++filter p = fromSeq . S.filter p . toSeq++partition p (N m xs) = (N (k-1) ys, N (m-k) zs)+ where (ys,zs) = S.partition p xs+ k = S.size ys++takeWhile p = fromSeq . S.reverse . S.takeWhile p . S.reverse . toSeq+dropWhile p = fromSeq . S.reverse . S.dropWhile p . S.reverse . toSeq++splitWhile p (N m xs) = (N (k-1) (S.reverse ys), N (m-k) (S.reverse zs))+ where (ys,zs) = S.splitWhile p (S.reverse xs)+ k = S.size ys++zip (N m xs) (N n ys)+ | m < n = N m (S.zip xs (S.drop (n-m) ys))+ | m > n = N n (S.zip (S.drop (m-n) xs) ys)+ | otherwise = N m (S.zip xs ys)+zip3 (N l xs) (N m ys) (N n zs) = N k (S.zip3 xs' ys' zs')+ where k = min l (min m n)+ xs' = if l == k then xs else S.drop (l-k) xs+ ys' = if m == k then ys else S.drop (m-k) ys+ zs' = if n == k then zs else S.drop (n-k) zs++zipWith f (N m xs) (N n ys)+ | m < n = N m (S.zipWith f xs (S.drop (n-m) ys))+ | m > n = N n (S.zipWith f (S.drop (m-n) xs) ys)+ | otherwise = N m (S.zipWith f xs ys)+zipWith3 f (N l xs) (N m ys) (N n zs) = N k (S.zipWith3 f xs' ys' zs')+ where k = min l (min m n)+ xs' = if l == k then xs else S.drop (l-k) xs+ ys' = if m == k then ys else S.drop (m-k) ys+ zs' = if n == k then zs else S.drop (n-k) zs++unzip (N m xys) = (N m xs, N m ys)+ where (xs,ys) = S.unzip xys++unzip3 (N m xyzs) = (N m xs, N m ys, N m zs)+ where (xs,ys,zs) = S.unzip3 xyzs++unzipWith f g (N m xys) = (N m xs, N m ys)+ where (xs,ys) = S.unzipWith f g xys++unzipWith3 f g h (N m xyzs) = (N m xs, N m ys, N m zs)+ where (xs,ys,zs) = S.unzipWith3 f g h xyzs++strict s@(N i s') = S.strict s' `seq` s+strictWith f s@(N i s') = S.strictWith f s' `seq` s++structuralInvariant (N i s) = i == ((S.size s) - 1)++-- instances++instance S.Sequence s => S.Sequence (Rev s) where+ {lcons = lcons; rcons = rcons;+ lview = lview; lhead = lhead; ltail = ltail;+ lheadM = lheadM; ltailM = ltailM; rheadM = rheadM; rtailM = rtailM;+ rview = rview; rhead = rhead; rtail = rtail; null = null;+ 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; reducer' = reducer'; reducel = reducel;+ reducel' = reducel'; reduce1 = reduce1; 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 = instanceName}++instance S.Sequence s => Functor (Rev s) where+ fmap = map++instance S.Sequence s => Monad (Rev s) where+ return = singleton+ xs >>= k = concatMap k xs++instance S.Sequence s => MonadPlus (Rev s) where+ mplus = append+ mzero = empty++instance Eq (s a) => Eq (Rev s a) where+ (N m xs) == (N n ys) = (m == n) && (xs == ys)++instance (S.Sequence s, Ord a, Eq (s a)) => Ord (Rev s a) where+ compare = defaultCompare++instance (S.Sequence s, Show (s a)) => Show (Rev s a) where+ showsPrec i xs rest+ | i == 0 = L.concat [ moduleName,".fromSeq ",showsPrec 10 (toSeq xs) rest]+ | otherwise = L.concat ["(",moduleName,".fromSeq ",showsPrec 10 (toSeq xs) (')':rest)]++instance (S.Sequence s, Read (s a)) => Read (Rev s a) where+ readsPrec i xs = maybeParens p xs+ where p xs = tokenMatch (moduleName++".fromSeq") xs+ >>= readsPrec 10+ >>= \(l,rest) -> return (fromSeq l,rest)++instance (S.Sequence s, Arbitrary (s a)) => Arbitrary (Rev s a) where+ arbitrary = do xs <- arbitrary+ return (fromSeq xs)++ coarbitrary xs = coarbitrary (toSeq xs)++instance S.Sequence s => Monoid (Rev s a) where+ mempty = empty+ mappend = append
+ src/Data/Edison/Seq/SimpleQueue.hs view
@@ -0,0 +1,369 @@+-- |+-- Module : Data.Edison.Seq.SimpleQueue+-- 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)+--+-- Simple Queues. All operations have running times as listed in+-- "Data.Edison.Seq" except for the following:+--+-- * rcons, fromList @O( 1 )@+--+-- * lview, ltail* @O( 1 )@ if single threaded, @O( n )@ otherwise+--+-- * inBounds, lookup, update, drop, splitAt @O( n )@+--+-- /References:/+--+-- * Chris Okasaki. /Purely Functional Data Structures/. 1998.+-- Section 5.2.+--+-- * F. Warren Burton. \"An efficient functional implementation of FIFO queues\".+-- /Information Processing Letters/, 14(5):205-206, July 1982.++module Data.Edison.Seq.SimpleQueue (+ -- * Sequence Type+ Seq, -- instance of Sequence, Functor, Monad, MonadPlus++ -- * Sequence Operations+ empty,singleton,lcons,rcons,append,lview,lhead,ltail,rview,rhead,rtail,+ lheadM,ltailM,rheadM,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,foldlWithIndex,foldrWithIndex',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 Data.Edison.Prelude+import qualified Data.Edison.Seq as S ( Sequence(..) )+import Data.Edison.Seq.Defaults+import qualified Data.Edison.Seq.ListSeq as L+import Data.Monoid+import Control.Monad+import Test.QuickCheck++-- signatures for exported functions+moduleName :: String+empty :: Seq a+singleton :: a -> Seq a+lcons :: a -> Seq a -> Seq a+rcons :: a -> Seq a -> Seq a+append :: Seq a -> Seq a -> Seq a+lview :: (Monad m) => Seq a -> m (a, Seq a)+lhead :: Seq a -> a+lheadM :: (Monad m) => Seq a -> m a+ltail :: Seq a -> Seq a+ltailM :: (Monad m) => Seq a -> m (Seq a)+rview :: (Monad m) => Seq a -> m (a, Seq a)+rhead :: Seq a -> a+rheadM :: (Monad m) => Seq a -> m a+rtail :: Seq a -> Seq a+rtailM :: (Monad m) => Seq a -> m (Seq a)+null :: Seq a -> Bool+size :: Seq a -> Int+concat :: Seq (Seq a) -> Seq a+reverse :: Seq a -> Seq a+reverseOnto :: Seq a -> Seq a -> Seq a+fromList :: [a] -> Seq a+toList :: Seq a -> [a]+map :: (a -> b) -> Seq a -> Seq b+concatMap :: (a -> Seq b) -> Seq a -> Seq b+fold :: (a -> b -> b) -> b -> Seq a -> b+fold' :: (a -> b -> b) -> b -> Seq a -> b+fold1 :: (a -> a -> a) -> Seq a -> a+fold1' :: (a -> a -> a) -> Seq a -> a+foldr :: (a -> b -> b) -> b -> Seq a -> b+foldl :: (b -> a -> b) -> b -> Seq a -> b+foldr1 :: (a -> a -> a) -> Seq a -> a+foldl1 :: (a -> a -> a) -> Seq a -> a+reducer :: (a -> a -> a) -> a -> Seq a -> a+reducel :: (a -> a -> a) -> a -> Seq a -> a+reduce1 :: (a -> a -> a) -> Seq a -> a+foldr' :: (a -> b -> b) -> b -> Seq a -> b+foldl' :: (b -> a -> b) -> b -> Seq a -> b+foldr1' :: (a -> a -> a) -> Seq a -> a+foldl1' :: (a -> a -> a) -> Seq a -> a+reducer' :: (a -> a -> a) -> a -> Seq a -> a+reducel' :: (a -> a -> a) -> a -> Seq a -> a+reduce1' :: (a -> a -> a) -> Seq a -> a+copy :: Int -> a -> Seq a+inBounds :: Int -> Seq a -> Bool+lookup :: Int -> Seq a -> a+lookupM :: (Monad m) => Int -> Seq a -> m a+lookupWithDefault :: a -> Int -> Seq a -> a+update :: Int -> a -> Seq a -> Seq a+adjust :: (a -> a) -> Int -> Seq a -> Seq a+mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b+foldrWithIndex :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex :: (b -> Int -> a -> b) -> b -> Seq a -> b+foldrWithIndex' :: (Int -> a -> b -> b) -> b -> Seq a -> b+foldlWithIndex' :: (b -> Int -> a -> b) -> b -> Seq a -> b+take :: Int -> Seq a -> Seq a+drop :: Int -> Seq a -> Seq a+splitAt :: Int -> Seq a -> (Seq a, Seq a)+subseq :: Int -> Int -> Seq a -> Seq a+filter :: (a -> Bool) -> Seq a -> Seq a+partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+takeWhile :: (a -> Bool) -> Seq a -> Seq a+dropWhile :: (a -> Bool) -> Seq a -> Seq a+splitWhile :: (a -> Bool) -> Seq a -> (Seq a, Seq a)+zip :: Seq a -> Seq b -> Seq (a,b)+zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c)+zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c+zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d+unzip :: Seq (a,b) -> (Seq a, Seq b)+unzip3 :: Seq (a,b,c) -> (Seq a, Seq b, Seq c)+unzipWith :: (a -> b) -> (a -> c) -> Seq a -> (Seq b, Seq c)+unzipWith3 :: (a -> b) -> (a -> c) -> (a -> d) -> Seq a -> (Seq b, Seq c, Seq d)+strict :: Seq a -> Seq a+strictWith :: (a -> b) -> Seq a -> Seq a+structuralInvariant :: Seq a -> Bool++moduleName = "Data.Edison.Seq.SimpleQueue"+++data Seq a = Q [a] [a]+ -- invariant: front empty only if rear also empty++-- not exported+makeQ [] ys = Q (L.reverse ys) []+makeQ xs ys = Q xs ys++empty = Q [] []+singleton x = Q [x] []+lcons x (Q xs ys) = Q (x:xs) ys++rcons y (Q [] _) = Q [y] []+rcons y (Q xs ys) = Q xs (y:ys)++append (Q xs1 ys1) (Q xs2 ys2) =+ Q (xs1 ++ L.reverseOnto ys1 xs2) ys2++lview (Q [] _) = fail "SimpleQueue.lview: empty sequence"+lview (Q [x] ys) = return (x, Q (L.reverse ys) [])+lview (Q (x:xs) ys) = return (x, Q xs ys)++lhead (Q [] _) = error "SimpleQueue.lhead: empty sequence"+lhead (Q (x:xs) _) = x++lheadM (Q [] _) = fail "SimpleQueue.lheadM: empty sequence"+lheadM (Q (x:xs) _) = return x++ltail (Q [x] ys) = Q (L.reverse ys) []+ltail (Q (x:xs) ys) = Q xs ys+ltail q@(Q [] _) = error "SimpleQueue.ltail: empty sequence"++ltailM (Q [x] ys) = return (Q (L.reverse ys) [])+ltailM (Q (x:xs) ys) = return (Q xs ys)+ltailM q@(Q [] _) = fail "SimpleQueue.ltailM: empty sequence"++rview (Q xs (y:ys)) = return (y, Q xs ys)+rview (Q xs []) =+ case L.rview xs of+ Nothing -> fail "SimpleQueue.rview: empty sequence"+ Just (x,xs') -> return (x, Q xs' [])++rhead (Q xs (y:ys)) = y+rhead (Q [] []) = error "SimpleQueue.rhead: empty sequence"+rhead (Q xs []) = L.rhead xs++rheadM (Q xs (y:ys)) = return y+rheadM (Q [] []) = fail "SimpleQueue.rheadM: empty sequence"+rheadM (Q xs []) = return (L.rhead xs)++rtail (Q xs (y:ys)) = Q xs ys+rtail q@(Q [] []) = error "SimpleQueue.rtail: empty sequence"+rtail (Q xs []) = Q (L.rtail xs) []++rtailM (Q xs (y:ys)) = return (Q xs ys)+rtailM q@(Q [] []) = fail "SimpleQueue.rtailM: empty sequence"+rtailM (Q xs []) = return (Q (L.rtail xs) [])++null (Q [] _) = True+null _ = False++size (Q xs ys) = length xs + length ys++reverse (Q xs []) = Q (L.reverse xs) []+reverse (Q xs ys) = Q ys xs++reverseOnto (Q xs1 ys1) (Q xs2 ys2) =+ Q (ys1 ++ L.reverseOnto xs1 xs2) ys2++fromList xs = Q xs []++toList (Q xs []) = xs+toList (Q xs ys) = xs ++ L.reverse ys++map f (Q xs ys) = Q (L.map f xs) (L.map f ys)++-- local fn on lists+revfoldr f e [] = e+revfoldr f e (x:xs) = revfoldr f (f x e) xs++revfoldr' f e [] = e+revfoldr' f e (x:xs) = e `seq` revfoldr' f (f x e) xs++-- local fn on lists+revfoldl f e [] = e+revfoldl f e (x:xs) = f (revfoldl f e xs) x++revfoldl' f e [] = e+revfoldl' f e (x:xs) = e `seq` f (revfoldl' f e xs) x++fold f e (Q xs ys) = L.foldr f (L.foldr f e ys) xs+fold' f e (Q xs ys) = L.foldl' (flip f) (L.foldl' (flip f) e ys) xs+fold1 = fold1UsingFold+fold1' = fold1'UsingFold'++foldr f e (Q xs ys) = L.foldr f (revfoldr f e ys) xs+foldr' f e (Q xs ys) = L.foldr' f (revfoldr' f e ys) xs++foldl f e (Q xs ys) = revfoldl f (L.foldl f e xs) ys+foldl' f e (Q xs ys) = revfoldl' f (L.foldl' f e xs) ys++foldr1 f (Q xs (y:ys)) = L.foldr f (revfoldr f y ys) xs+foldr1 f (Q [] []) = error "SimpleQueue.foldr1: empty sequence"+foldr1 f (Q xs []) = L.foldr1 f xs++foldr1' f (Q xs (y:ys)) = L.foldr' f (revfoldr' f y ys) xs+foldr1' f (Q [] []) = error "SimpleQueye.foldr1': empty sequence"+foldr1' f (Q xs []) = L.foldr1' f xs++foldl1 f (Q (x:xs) ys) = revfoldl f (L.foldl f x xs) ys+foldl1 f (Q [] _) = error "SimpleQueue.foldl1: empty sequence"++foldl1' f (Q (x:xs) ys) = revfoldl' f (L.foldl' f x xs) ys+foldl1' f (Q [] _) = error "SimpleQueue.foldl1': empty sequence"++filter p (Q xs ys) = makeQ (L.filter p xs) (L.filter p ys)++partition p (Q xs ys)+ = (makeQ xsT ysT, makeQ xsF ysF)+ where+ (xsT,xsF) = L.partition p xs+ (ysT,ysF) = L.partition p ys++strict s@(Q xs ys) = L.strict xs `seq` L.strict ys `seq` s+strictWith f s@(Q xs ys) = L.strictWith f xs `seq` L.strictWith f ys `seq` s++-- the remaining functions all use defaults++concat = concatUsingFoldr+concatMap = concatMapUsingFoldr+reducer = reducerUsingReduce1+reducer' = reducer'UsingReduce1'+reducel = reducelUsingReduce1+reducel' = reducel'UsingReduce1'+reduce1 = reduce1UsingLists+reduce1' = reduce1'UsingLists+copy = copyUsingLists+inBounds = inBoundsUsingLookupM+lookup = lookupUsingLookupM+lookupM = lookupMUsingDrop+lookupWithDefault = lookupWithDefaultUsingLookupM+update = updateUsingAdjust+adjust = adjustUsingLists+mapWithIndex = mapWithIndexUsingLists+foldrWithIndex = foldrWithIndexUsingLists+foldrWithIndex' = foldrWithIndex'UsingLists+foldlWithIndex = foldlWithIndexUsingLists+foldlWithIndex' = foldlWithIndex'UsingLists+take = takeUsingLists+drop = dropUsingLists+splitAt = splitAtDefault+subseq = subseqDefault+takeWhile = takeWhileUsingLview+dropWhile = dropWhileUsingLview+splitWhile = splitWhileUsingLview+zip = zipUsingLists+zip3 = zip3UsingLists+zipWith = zipWithUsingLists+zipWith3 = zipWith3UsingLists+unzip = unzipUsingLists+unzip3 = unzip3UsingLists+unzipWith = unzipWithUsingLists+unzipWith3 = unzipWith3UsingLists++-- invariant: +-- * front empty only if rear also empty++structuralInvariant (Q x y) = not (L.null x) || L.null y++-- instances++instance S.Sequence Seq where+ {lcons = lcons; rcons = rcons;+ lview = lview; lhead = lhead; ltail = ltail;+ lheadM = lheadM; ltailM = ltailM; rheadM = rheadM; rtailM = rtailM;+ rview = rview; rhead = rhead; rtail = rtail; null = null;+ 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; reducer' = reducer'; reducel = reducel;+ reducel' = reducel'; reduce1 = reduce1; 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}++instance Functor Seq where+ fmap = map++instance Monad Seq where+ return = singleton+ xs >>= k = concatMap k xs++instance MonadPlus Seq where+ mplus = append+ mzero = empty++instance Eq a => Eq (Seq a) where+ q1 == q2 = toList q1 == toList q2++instance Ord a => Ord (Seq a) where+ compare = defaultCompare++instance Show a => Show (Seq a) where+ showsPrec = showsPrecUsingToList++instance Read a => Read (Seq a) where+ readsPrec = readsPrecUsingFromList++instance Arbitrary a => Arbitrary (Seq a) where+ arbitrary = do xs <- arbitrary+ ys <- arbitrary+ return (if L.null xs then Q ys [] else Q xs ys)++ coarbitrary (Q xs ys) = coarbitrary xs . coarbitrary ys++instance Monoid (Seq a) where+ mempty = empty+ mappend = append
+ src/Data/Edison/Seq/SizedSeq.hs view
@@ -0,0 +1,355 @@+-- |+-- Module : Data.Edison.Seq.SizedSeq+-- 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)+--+-- This module defines a sequence adaptor @Sized s@.+-- If @s@ is a sequence type constructor, then @Sized s@+-- is a sequence type constructor that is identical to @s@,+-- except that it also keeps track of the current size of+-- each sequence.+--+-- All time complexities are determined by the underlying+-- sequence, except that size becomes @O( 1 )@.++module Data.Edison.Seq.SizedSeq (+ -- * Sized Sequence Type+ Sized, -- Sized s instance of Sequence, Functor, Monad, MonadPlus++ -- * Sequence Operations+ empty,singleton,lcons,rcons,append,lview,lhead,ltail,rview,rhead,rtail,+ lheadM,ltailM,rheadM,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,foldlWithIndex,foldrWithIndex',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,instanceName,++ -- * Other supported operations+ fromSeq,toSeq+) 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 Data.Edison.Prelude+import qualified Data.Edison.Seq as S+import qualified Data.Edison.Seq.ListSeq as L+import Data.Edison.Seq.Defaults -- only used by concatMap+import Data.Monoid+import Control.Monad+import Test.QuickCheck+++-- signatures for exported functions+moduleName :: String+instanceName :: S.Sequence s => Sized s a -> String+empty :: S.Sequence s => Sized s a+singleton :: S.Sequence s => a -> Sized s a+lcons :: S.Sequence s => a -> Sized s a -> Sized s a+rcons :: S.Sequence s => a -> Sized s a -> Sized s a+append :: S.Sequence s => Sized s a -> Sized s a -> Sized s a+lview :: (S.Sequence s, Monad m) => Sized s a -> m (a, Sized s a)+lhead :: S.Sequence s => Sized s a -> a+lheadM :: (S.Sequence s, Monad m) => Sized s a -> m a+ltail :: S.Sequence s => Sized s a -> Sized s a+ltailM :: (S.Sequence s, Monad m) => Sized s a -> m (Sized s a)+rview :: (S.Sequence s, Monad m) => Sized s a -> m (a, Sized s a)+rhead :: S.Sequence s => Sized s a -> a+rheadM :: (S.Sequence s, Monad m) => Sized s a -> m a+rtail :: S.Sequence s => Sized s a -> Sized s a+rtailM :: (S.Sequence s, Monad m) => Sized s a -> m (Sized s a)+null :: S.Sequence s => Sized s a -> Bool+size :: S.Sequence s => Sized s a -> Int+concat :: S.Sequence s => Sized s (Sized s a) -> Sized s a+reverse :: S.Sequence s => Sized s a -> Sized s a+reverseOnto :: S.Sequence s => Sized s a -> Sized s a -> Sized s a+fromList :: S.Sequence s => [a] -> Sized s a+toList :: S.Sequence s => Sized s a -> [a]+map :: S.Sequence s => (a -> b) -> Sized s a -> Sized s b+concatMap :: S.Sequence s => (a -> Sized s b) -> Sized s a -> Sized s b+fold :: S.Sequence s => (a -> b -> b) -> b -> Sized s a -> b+fold' :: S.Sequence s => (a -> b -> b) -> b -> Sized s a -> b+fold1 :: S.Sequence s => (a -> a -> a) -> Sized s a -> a+fold1' :: S.Sequence s => (a -> a -> a) -> Sized s a -> a+foldr :: S.Sequence s => (a -> b -> b) -> b -> Sized s a -> b+foldl :: S.Sequence s => (b -> a -> b) -> b -> Sized s a -> b+foldr1 :: S.Sequence s => (a -> a -> a) -> Sized s a -> a+foldl1 :: S.Sequence s => (a -> a -> a) -> Sized s a -> a+reducer :: S.Sequence s => (a -> a -> a) -> a -> Sized s a -> a+reducel :: S.Sequence s => (a -> a -> a) -> a -> Sized s a -> a+reduce1 :: S.Sequence s => (a -> a -> a) -> Sized s a -> a+foldr' :: S.Sequence s => (a -> b -> b) -> b -> Sized s a -> b+foldl' :: S.Sequence s => (b -> a -> b) -> b -> Sized s a -> b+foldr1' :: S.Sequence s => (a -> a -> a) -> Sized s a -> a+foldl1' :: S.Sequence s => (a -> a -> a) -> Sized s a -> a+reducer' :: S.Sequence s => (a -> a -> a) -> a -> Sized s a -> a+reducel' :: S.Sequence s => (a -> a -> a) -> a -> Sized s a -> a+reduce1' :: S.Sequence s => (a -> a -> a) -> Sized s a -> a+copy :: S.Sequence s => Int -> a -> Sized s a+inBounds :: S.Sequence s => Int -> Sized s a -> Bool+lookup :: S.Sequence s => Int -> Sized s a -> a+lookupM :: (S.Sequence s, Monad m) => Int -> Sized s a -> m a+lookupWithDefault :: S.Sequence s => a -> Int -> Sized s a -> a+update :: S.Sequence s => Int -> a -> Sized s a -> Sized s a+adjust :: S.Sequence s => (a -> a) -> Int -> Sized s a -> Sized s a+mapWithIndex :: S.Sequence s => (Int -> a -> b) -> Sized s a -> Sized s b+foldrWithIndex :: S.Sequence s => (Int -> a -> b -> b) -> b -> Sized s a -> b+foldlWithIndex :: S.Sequence s => (b -> Int -> a -> b) -> b -> Sized s a -> b+foldrWithIndex' :: S.Sequence s => (Int -> a -> b -> b) -> b -> Sized s a -> b+foldlWithIndex' :: S.Sequence s => (b -> Int -> a -> b) -> b -> Sized s a -> b+take :: S.Sequence s => Int -> Sized s a -> Sized s a+drop :: S.Sequence s => Int -> Sized s a -> Sized s a+splitAt :: S.Sequence s => Int -> Sized s a -> (Sized s a, Sized s a)+subseq :: S.Sequence s => Int -> Int -> Sized s a -> Sized s a+filter :: S.Sequence s => (a -> Bool) -> Sized s a -> Sized s a+partition :: S.Sequence s => (a -> Bool) -> Sized s a -> (Sized s a, Sized s a)+takeWhile :: S.Sequence s => (a -> Bool) -> Sized s a -> Sized s a+dropWhile :: S.Sequence s => (a -> Bool) -> Sized s a -> Sized s a+splitWhile :: S.Sequence s => (a -> Bool) -> Sized s a -> (Sized s a, Sized s a)+zip :: S.Sequence s => Sized s a -> Sized s b -> Sized s (a,b)+zip3 :: S.Sequence s => Sized s a -> Sized s b -> Sized s c -> Sized s (a,b,c)+zipWith :: S.Sequence s => (a -> b -> c) -> Sized s a -> Sized s b -> Sized s c+zipWith3 :: S.Sequence s => (a -> b -> c -> d) -> Sized s a -> Sized s b -> Sized s c -> Sized s d+unzip :: S.Sequence s => Sized s (a,b) -> (Sized s a, Sized s b)+unzip3 :: S.Sequence s => Sized s (a,b,c) -> (Sized s a, Sized s b, Sized s c)+unzipWith :: S.Sequence s => (a -> b) -> (a -> c) -> Sized s a -> (Sized s b, Sized s c)+unzipWith3 :: S.Sequence s => (a -> b) -> (a -> c) -> (a -> d) -> Sized s a -> (Sized s b, Sized s c, Sized s d)+strict :: S.Sequence s => Sized s a -> Sized s a+strictWith :: S.Sequence s => (a -> b) -> Sized s a -> Sized s a+structuralInvariant :: S.Sequence s => Sized s a -> Bool++-- bonus functions, not in Sequence signature+fromSeq :: S.Sequence s => s a -> Sized s a+toSeq :: S.Sequence s => Sized s a -> s a++++moduleName = "Data.Edison.Seq.SizedSeq"+instanceName (N n s) = "SizedSeq(" ++ S.instanceName s ++ ")"++data Sized s a = N !Int (s a)++fromSeq xs = N (S.size xs) xs+toSeq (N n xs) = xs++empty = N 0 S.empty+singleton x = N 1 (S.singleton x)+lcons x (N n xs) = N (n+1) (S.lcons x xs)+rcons x (N n xs) = N (n+1) (S.rcons x xs)+append (N m xs) (N n ys) = N (m+n) (S.append xs ys)++lview (N n xs) = case S.lview xs of+ Nothing -> fail "SizedSeq.lview: empty sequence"+ Just (x,xs) -> return (x, N (n-1) xs)++lhead (N n xs) = S.lhead xs++lheadM (N n xs) = S.lheadM xs++ltail (N 0 xs) = error "SizedSeq.ltail: empty sequence"+ltail (N n xs) = N (n-1) (S.ltail xs)++ltailM (N 0 xs) = fail "SizedSeq.ltailM: empty sequence"+ltailM (N n xs) = return (N (n-1) (S.ltail xs))++rview (N n xs) = case S.rview xs of+ Nothing -> fail "SizedSeq.rview: empty sequence"+ Just (x,xs) -> return (x, N (n-1) xs)+ +rhead (N n xs) = S.rhead xs++rheadM (N n xs) = S.rheadM xs++rtail (N 0 xs) = error "SizedSeq.rtail: empty sequence"+rtail (N n xs) = N (n-1) (S.rtail xs)++rtailM (N 0 xs) = fail "SizedSeq.rtailM: empty sequence"+rtailM (N n xs) = return (N (n-1) (S.rtail xs))++null (N n xs) = n == 0+size (N n xs) = n+concat (N n xss) = fromSeq (S.concat (S.map toSeq xss))+reverse (N n xs) = N n (S.reverse xs)+reverseOnto (N m xs) (N n ys) = N (m+n) (S.reverseOnto xs ys)+fromList = fromSeq . S.fromList+toList (N n xs) = S.toList xs+map f (N n xs) = N n (S.map f xs)++concatMap = concatMapUsingFoldr -- only function that uses a default++fold f e (N n xs) = S.fold f e xs+fold' f e (N n xs) = S.fold' f e xs+fold1 f (N n xs) = S.fold1 f xs+fold1' f (N n xs) = S.fold1' f xs+foldr f e (N n xs) = S.foldr f e xs+foldr' f e (N n xs) = S.foldr' f e xs+foldl f e (N n xs) = S.foldl f e xs+foldl' f e (N n xs) = S.foldl' f e xs+foldr1 f (N n xs) = S.foldr1 f xs+foldr1' f (N n xs) = S.foldr1' f xs+foldl1 f (N n xs) = S.foldl1 f xs+foldl1' f (N n xs) = S.foldl1' f xs+reducer f e (N n xs) = S.reducer f e xs+reducer' f e (N n xs) = S.reducer' f e xs+reducel f e (N n xs) = S.reducel f e xs+reducel' f e (N n xs) = S.reducel' f e xs+reduce1 f (N n xs) = S.reduce1 f xs+reduce1' f (N n xs) = S.reduce1' f xs++copy n x + | n <= 0 = empty+ | otherwise = N n (S.copy n x)++inBounds i (N n xs) = (i >= 0) && (i < n)+lookup i (N n xs) = S.lookup i xs+lookupM i (N n xs) = S.lookupM i xs+lookupWithDefault d i (N n xs) = S.lookupWithDefault d i xs+update i x (N n xs) = N n (S.update i x xs)+adjust f i (N n xs) = N n (S.adjust f i xs)+mapWithIndex f (N n xs) = N n (S.mapWithIndex f xs)+foldrWithIndex f e (N n xs) = S.foldrWithIndex f e xs+foldrWithIndex' f e (N n xs) = S.foldrWithIndex' f e xs+foldlWithIndex f e (N n xs) = S.foldlWithIndex f e xs+foldlWithIndex' f e (N n xs) = S.foldlWithIndex' f e xs++take i original@(N n xs)+ | i <= 0 = empty+ | i >= n = original+ | otherwise = N i (S.take i xs)++drop i original@(N n xs)+ | i <= 0 = original+ | i >= n = empty+ | otherwise = N (n-i) (S.drop i xs)++splitAt i original@(N n xs)+ | i <= 0 = (empty, original)+ | i >= n = (original, empty)+ | otherwise = let (ys,zs) = S.splitAt i xs+ in (N i ys, N (n-i) zs)++subseq i len original@(N n xs)+ | i <= 0 = take len original+ | i >= n || len <= 0 = empty+ | i+len >= n = N (n-i) (S.drop i xs)+ | otherwise = N len (S.subseq i len xs)++filter p = fromSeq . S.filter p . toSeq++partition p (N n xs) = (N m ys, N (n-m) zs)+ where (ys,zs) = S.partition p xs+ m = S.size ys++takeWhile p = fromSeq . S.takeWhile p . toSeq+dropWhile p = fromSeq . S.dropWhile p . toSeq++splitWhile p (N n xs) = (N m ys, N (n-m) zs)+ where (ys,zs) = S.splitWhile p xs+ m = S.size ys++zip (N m xs) (N n ys) = N (min m n) (S.zip xs ys)+zip3 (N l xs) (N m ys) (N n zs) = N (min l (min m n)) (S.zip3 xs ys zs)++zipWith f (N m xs) (N n ys) = N (min m n) (S.zipWith f xs ys)+zipWith3 f (N l xs) (N m ys) (N n zs) = N (min l (min m n)) (S.zipWith3 f xs ys zs)++unzip (N n xys) = (N n xs, N n ys)+ where (xs,ys) = S.unzip xys++unzip3 (N n xyzs) = (N n xs, N n ys, N n zs)+ where (xs,ys,zs) = S.unzip3 xyzs++unzipWith f g (N n xys) = (N n xs, N n ys)+ where (xs,ys) = S.unzipWith f g xys++unzipWith3 f g h (N n xyzs) = (N n xs, N n ys, N n zs)+ where (xs,ys,zs) = S.unzipWith3 f g h xyzs++strict s@(N i s') = S.strict s' `seq` s+strictWith f s@(N i s') = S.strictWith f s' `seq` s++structuralInvariant (N i s) = i == S.size s++-- instances++instance S.Sequence s => S.Sequence (Sized s) where+ {lcons = lcons; rcons = rcons;+ lview = lview; lhead = lhead; ltail = ltail;+ lheadM = lheadM; ltailM = ltailM; rheadM = rheadM; rtailM = rtailM;+ rview = rview; rhead = rhead; rtail = rtail; null = null;+ 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; reducer' = reducer'; reducel = reducel;+ reducel' = reducel'; reduce1 = reduce1; 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 = instanceName}++instance S.Sequence s => Functor (Sized s) where+ fmap = map++instance S.Sequence s => Monad (Sized s) where+ return = singleton+ xs >>= k = concatMap k xs++instance S.Sequence s => MonadPlus (Sized s) where+ mplus = append+ mzero = empty+++instance Eq (s a) => Eq (Sized s a) where+ (N m xs) == (N n ys) = (m == n) && (xs == ys)+ -- this is probably identical to the code that would be+ -- generated by "deriving (Eq)", but I wanted to be *sure*+ -- that the sizes were compared before the inner sequences++instance (S.Sequence s, Ord a, Eq (s a)) => Ord (Sized s a) where+ compare = defaultCompare++instance (S.Sequence s, Show (s a)) => Show (Sized s a) where+ showsPrec i xs rest+ | i == 0 = L.concat [ moduleName,".fromSeq ",showsPrec 10 (toSeq xs) rest]+ | otherwise = L.concat ["(",moduleName,".fromSeq ",showsPrec 10 (toSeq xs) (')':rest)]++instance (S.Sequence s, Read (s a)) => Read (Sized s a) where+ readsPrec i xs = maybeParens p xs+ where p xs = tokenMatch (moduleName++".fromSeq") xs+ >>= readsPrec 10+ >>= \(l,rest) -> return (fromSeq l, rest)++instance (S.Sequence s, Arbitrary (s a)) => Arbitrary (Sized s a) where+ arbitrary = do xs <- arbitrary+ return (fromSeq xs)++ coarbitrary xs = coarbitrary (toSeq xs)++instance S.Sequence s => Monoid (Sized s a) where+ mempty = empty+ mappend = append