------------------------------------------------------------------------------- |-- Module : Data.Map.AVL-- Copyright : (c) Adrian Hey 2005,2006-- License : BSD3---- Maintainer : http://homepages.nildram.co.uk/~ahey/em.png-- Stability : provisional-- Portability : portable---- This module provides an AVL tree based clone of the base package Data.Map.---- There are some differences though..---- * 'size' is O(n), not O(1). Consequently, indexed access is disabled.---- * The showTree and showTreeWith functions are not implemented.---- * Some other functions are not yet implemented.-------------------------------------------------------------------------------moduleData.Map.AVL(-- * Map typeMap-- * Operators,(!),(\\)-- * Query,null,size,member,lookup,findWithDefault-- * Construction,empty,singleton-- ** Insertion,insert,insertWith,insertWithKey,insertLookupWithKey-- ** Delete\/Update,delete,adjust,alter,adjustWithKey,update,updateWithKey,updateLookupWithKey-- * Combine-- ** Union,union,unionWith,unionWithKey,unions,unionsWith-- ** Difference,difference,differenceWith,differenceWithKey-- ** Intersection,intersection,intersectionWith,intersectionWithKey-- * Traversal-- ** Map,map,mapWithKey,mapAccum-- , mapAccumWithKey-- , mapKeys-- , mapKeysWith-- , mapKeysMonotonic-- ** Fold,fold,foldWithKey-- * Conversion,elems,keys,keysSet,liftKeysSet,assocs,unsafeFromTree,toTree,toList,fromList,fromListWith,fromListWithKey-- ** Ordered lists,toAscList,fromAscList,fromAscListWith,fromAscListWithKey,fromDistinctAscList-- * Filter ,filter,filterWithKey,partition,partitionWithKey,split,splitLookup-- * Submap,isSubmapOf,isSubmapOfBy-- , isProperSubmapOf, isProperSubmapOfBy-- * Indexed -- , lookupIndex-- , findIndex-- , elemAt-- , updateAt-- , deleteAt-- * Min\/Max,findMin,findMax,deleteMin,deleteMax,deleteFindMin,deleteFindMax-- , updateMin-- , updateMax-- , updateMinWithKey-- , updateMaxWithKey-- * Debugging-- , showTree-- , showTreeWith-- , valid)whereimportPreludehiding(lookup,map,filter,foldr,foldl,null)importqualifiedData.ListasListimportData.Monoid-- import qualified Data.Maybe as MaybeimportqualifiedData.Set.AVLasSet-- import Data.MonoidimportData.Foldablehiding(toList,find,fold)importqualifiedData.COrderingasCOrderingimportqualifiedData.Tree.AVLasAVL-- import qualified Data.Tree.AVL.Test.Utils as AVLimportData.Typeable#include "Typeable.h"INSTANCE_TYPEABLE2(Map,mapTc,"Data.Map.AVL")---------------------------------------------------------- local combining comparison utilities ----------------------------------------------------------------readValCC::Ordk=>k->(k,a)->COrdering.COrderingareadValCCk(k',a)=casecomparekk'ofLT->COrdering.LtEQ->COrdering.EqaGT->COrdering.Gtmcmp::Orda=>(a,b)->(a,c)->COrdering.COrdering(a,b)mcmp(k,a)(k',_)=casecomparekk'ofLT->COrdering.LtEQ->COrdering.Eq(k,a)GT->COrdering.Gtmfcmp::Ordk=>(k->a->b->c)->(k,a)->(k,b)->COrdering.COrdering(k,c)mfcmpf(k,a)(k',b)=casecomparekk'ofLT->COrdering.LtEQ->COrdering.Eq(k,fkab)GT->COrdering.Gtmmfcmp::(Functorf,Ordk)=>(k->a->b->fc)->(k,a)->(k,b)->COrdering.COrdering(f(k,c))mmfcmpf(k,a)(k',b)=casecomparekk'ofLT->COrdering.LtEQ->COrdering.Eq$fmap(\c->(k,c))$fkabGT->COrdering.Gtinfixl9!,\\-- toOrdering::COrdering.COrderinga->OrderingtoOrderingc=casecofCOrdering.Lt->LTCOrdering.Eq_->EQCOrdering.Gt->GTtoOrd::(a->b->COrdering.COrderingc)->a->b->OrderingtoOrdfa=toOrdering.fa-- | A Map from keys @k@ to values @a@. newtypeMapka=Map(AVL.AVL(k,a))-- deriving (Eq, Ord, Show)instance(Eqk,Eqa)=>Eq(Mapka)wherem1==m2=toListm1==toListm2instance(Ordk,Orda)=>Ord(Mapka)wherecomparem1m2=compare(toListm1)(toListm2)showSet::(Showa)=>[a]->ShowSshowSet[]=showString"{}"showSet(x:xs)=showChar'{'.showsx.showTailxswhereshowTail[]=showChar'}'showTail(x':xs')=showString", ".showsx'.showTailxs'instance(Showk,Showa)=>Show(Mapka)whereshowsPrec_(Mapt)=showSet(AVL.asListLt)-- | /O(1)/. The empty map.empty::Mapkaempty=Map(AVL.empty)-- | /O(1)/. A map with a single element.singleton::k->a->Mapkasingletonka=k`seq`Map(AVL.singleton(k,a))-- | /O(1)/. Is the map empty?null::Mapka->Boolnull(Mapt)=AVL.isEmptyt-- | /O(n)/. The number of elements in the map.size::Mapka->Intsize(Mapt)=AVL.sizet-- | /O(log n)/. Is the key a member of the map?member::Ordk=>k->Mapka->Boolmemberk(Mapt)=k`seq`AVL.genContainst(comparek.fst)-- | /O(log n)/. Find the value at a key.-- Calls 'error' when the element can not be found.(!)::Ordk=>Mapka->k->a(!)mk=findkm-- | /O(log n)/. Find the value at a key.-- Calls 'error' when the element can not be found.find::Ordk=>k->Mapka->afind=findWithDefault(error"Map.find: element not in the map")-- | /O(log n)/. Lookup the value at a key in the map.lookup::(Monadm,Ordk)=>k->Mapka->malookupk(Mapt)=k`seq`maybe(fail"AvlMap.lookup: Key not found")return(AVL.genTryReadt(readValCCk))-- | /O(log n)/. The expression @('findWithDefault' def k map)@ returns-- the value at key @k@ or returns @def@ when the key is not in the map.findWithDefault::Ordk=>a->k->Mapka->afindWithDefaultdefk(Mapt)=k`seq`AVL.genDefaultReaddeft(readValCCk)-- | /O(log n)/. Insert a new key and value in the map.-- If the key is already present in the map, the associated value is-- replaced with the supplied value, i.e. 'insert' is equivalent to-- @'insertWith' 'const'@.insert::Ordk=>k->a->Mapka->Mapkainsertka(Mapt)=k`seq`Map(AVL.genPush(mcmp(k,a))(k,a)t)-- | /O(log n)/. Insert with a combining function.insertWith::Ordk=>(a->a->a)->k->a->Mapka->MapkainsertWithf=insertWithKey(\_zy->fzy)-- | /O(log n)/. Insert with a combining function.insertWithKey::Ordk=>(k->a->a->a)->k->a->Mapka->MapkainsertWithKeyfka(Mapt)=k`seq`Map(AVL.genPush(mfcmpf(k,a))(k,a)t)-- | /O(log n)/. The expression (@'insertLookupWithKey' f k x map@)-- is a pair where the first element is equal to (@'lookup' k map@)-- and the second element equal to (@'insertWithKey' f k x map@).---- TODO: only one traversal. This requires fiddling with AVL.Push.insertLookupWithKey::Ordk=>(k->a->a->a)->k->a->Mapka->(Maybea,Mapka)insertLookupWithKeyfkam=(lookupkm,insertWithKeyfkam)-- | /O(log n)/. Delete a key and its value from the map. When the key is not-- a member of the map, the original map is returned.delete::Ordk=>k->Mapka->Mapkadeletek(Mapt)=k`seq`Map(AVL.genDel(comparek.fst)t)-- | /O(n)/. Map a function over all values in the map.map::(a->b)->Mapka->Mapkbmapf=mapWithKey(\_x->fx)-- | /O(n)/. Map a function over all values in the map.mapWithKey::(k->a->b)->Mapka->MapkbmapWithKeyf(Mapt)=Map(AVL.mapAVLmft)wheremf(k',a')=(k',fk'a')-- | /O(n)/. The function 'mapAccum' threads an accumulating-- argument through the map in ascending order of keys.mapAccum::Ordk=>(a->b->(a,c))->a->Mapkb->(a,Mapkc)mapAccumfa=foldWithKey(\kb(s,m)->let(r,c)=fsbin(r,insertkcm))(a,empty)-- | /O(n)/. Filter all values that satisfy the predicate.filter::Ordk=>(a->Bool)->Mapka->Mapkafilterp(Mapt)=Map(AVL.filterViaList(p.snd)t)-- | /O(n)/. Filter all keys\/values that satisfy the predicate.filterWithKey::Ordk=>(k->a->Bool)->Mapka->MapkafilterWithKeyp(Mapt)=Map(AVL.filterViaList(mpp)t)mp::(k->a->Bool)->(k,a)->Boolmpp(k,a)=pka-- | /O(n)/. partition the map according to a predicate. The first-- map contains all elements that satisfy the predicate, the second all-- elements that fail the predicate.partition::Ordk=>(a->Bool)->Mapka->(Mapka,Mapka)partitionp=partitionWithKey(\_x->px)-- | /O(n)/. partition the map according to a predicate. The first-- map contains all elements that satisfy the predicate, the second all-- elements that fail the predicate.partitionWithKey::Ordk=>(k->a->Bool)->Mapka->(Mapka,Mapka)partitionWithKeyp(Mapt)=let(t1,t2)=AVL.partitionAVL(mpp)tin(Mapt1,Mapt2)-- | /O(log n)/. The expression (@'split' x set@) is a pair @(set1,set2)@-- where all elements in @set1@ are lower than @x@ and all elements in-- @set2@ larger than @x@. @x@ is not found in neither @set1@ nor @set2@.split::Ordk=>k->Mapka->(Mapka,Mapka)splitk(Mapt)=(MaplessT,MapgreaterT)where(lessT,_,greaterT)=AVL.genFork(readValCCk)t-- | /O(log n)/. The expression (@'splitLookup' k map@) splits a map just-- like 'split' but also returns @'lookup' k map@.splitLookup::Ordk=>k->Mapka->(Mapka,Maybea,Mapka)splitLookupk(Mapt)=(MaplessT,a,MapgreaterT)where(lessT,a,greaterT)=AVL.genFork(readValCCk)t-- | /O(log n)/. The minimal key of the map.findMin::Mapka->(k,a)findMin(Mapt)=AVL.assertReadLt-- | /O(log n)/. Delete the minimal key.deleteMin::Mapka->MapkadeleteMin(Mapt)=Map$maybe(error"Set.deleteMin")id$AVL.tryDelLt-- | /O(log n)/. Delete and find the minimal element.deleteFindMin::Mapka->((k,a),Mapka)deleteFindMin(Mapt)=let((m,v),s)=AVL.assertPopLtin((m,v),Maps)-- | /O(log n)/. Delete and find the maximal element.deleteFindMax::Mapka->((k,a),Mapka)deleteFindMax(Mapt)=let(s,(m,v))=AVL.assertPopRtin((m,v),Maps)-- | /O(log n)/. The minimal key of the map.findMax::Mapka->(k,a)findMax(Mapt)=AVL.assertReadRt-- | /O(log n)/. Delete the minimal key.deleteMax::Mapka->MapkadeleteMax(Mapt)=Map$maybe(error"Set.deleteMax")id$AVL.tryDelRt-- | /O(n+m)/. Intersection of two maps. The values in the first-- map are returned, i.e. -- (@'intersection' m1 m2 == 'intersectionWith' 'const' m1 m2@).intersection::Ordk=>Mapka->Mapkb->Mapkaintersection(Mapt1)(Mapt2)=Map(AVL.genIntersectionmcmpt1t2)-- | /O(n+m)/. Intersection with a combining function.intersectionWith::Ordk=>(a->b->c)->Mapka->Mapkb->MapkcintersectionWithf=intersectionWithKey(\_xy->fxy)-- | /O(n+m)/. Intersection with a combining function.-- Intersection is more efficient on (bigset `intersection` smallset)intersectionWithKey::Ordk=>(k->a->b->c)->Mapka->Mapkb->MapkcintersectionWithKeyf(Mapt1)(Mapt2)=Map(AVL.genIntersection(mfcmpf)t1t2)-- | /O(n)/. Convert to a list of key\/value pairs.toList::Mapka->[(k,a)]toList(Mapt)=AVL.asListLt-- | /O(n)/. Convert to a list of key\/value pairs.toAscList::Mapka->[(k,a)]toAscList=toList-- | /O(n)/. Convert to a list of key\/value pairs.assocs::Mapka->[(k,a)]assocs=toList-- | /O(n)/. Convert to a list of keys.keys::Mapka->[k]keys=List.mapfst.toList-- | /O(n)/. The set of all keys of the map.keysSet::Mapka->Set.SetkkeysSet=Set.unsafeFromTree.fmapfst.toTree-- | /O(n)/. Apply a function to each element of a set and return the resulting map.liftKeysSet::(k->b)->Set.Setk->MapkbliftKeysSetf=unsafeFromTree.fmap(\k->(k,fk)).Set.toTree-- | /O(n)/. Convert to a list of values.elems::Mapka->[a]elems(Mapt)=List.mapsnd(AVL.asListLt)-- | /O(n)/. Fold the values in the map, such that-- @'fold' f z == 'Prelude.foldr' f z . 'elems'@.-- For example,---- > elems map = fold (:) [] map--fold::(a->b->b)->b->Mapka->bfoldf=foldWithKey(\_xc->fxc)foldWithKey::(k->a->b->b)->b->Mapka->bfoldWithKeyfz(Mapt)=AVL.foldlAVL'(\c(k,a)->fkac)zt-- | /O(n+m)/. See 'difference'.(\\)::Ordk=>Mapka->Mapkb->Mapkam1\\m2=differencem1m2-- | /O(n+m)/. Difference of two maps.difference::Ordk=>Mapka->Mapkb->Mapkadifference(Mapt1)(Mapt2)=Map(AVL.genDifference(toOrdmcmp)t1t2)-- | /O(n+m)/. Difference with a combining function.differenceWith::Ordk=>(a->b->Maybea)->Mapka->Mapkb->MapkadifferenceWithf=differenceWithKey(\_xy->fxy)differenceWithKey::Ordk=>(k->a->b->Maybea)->Mapka->Mapkb->MapkadifferenceWithKeyf(Mapt1)(Mapt2)=Map(AVL.genDifferenceMaybe(mmfcmpf)t1t2)-- | /O(n)/. Build a map from an ascending list of distinct elements in linear time.-- /The precondition is not checked./fromDistinctAscList::[(k,a)]->MapkafromDistinctAscList=Map.AVL.asTreeL-- | /O(n)/. Build a map from an ascending list in linear time.-- /The precondition (input list is ascending) is not checked./fromAscList::Eqk=>[(k,a)]->MapkafromAscList=fromAscListWithKey(\_x_->x)-- | /O(n)/. Build a map from an ascending list in linear time with a combining function for equal keys.-- /The precondition (input list is ascending) is not checked./fromAscListWith::Eqk=>(a->a->a)->[(k,a)]->MapkafromAscListWithf=fromAscListWithKey(\_xy->fxy)-- | /O(n)/. Build a map from an ascending list in linear time with a-- combining function for equal keys.-- /The precondition (input list is ascending) is not checked./fromAscListWithKey::Eqk=>(k->a->a->a)->[(k,a)]->MapkafromAscListWithKeyf=fromDistinctAscList.combineEqwhere-- [combineEq xs] combines equal elements with function [f] in an ordered list [xs]combineEqxs=casexsof[]->[][x]->[x](x:xx)->combineEq'xxxcombineEq'z[]=[z]combineEq'z@(kz,zz)(x@(kx,xx):xs)|kx==kz=letyy=fkxxxzzincombineEq'(kx,yy)xs|otherwise=z:combineEq'xxsfromList::Ordk=>[(k,a)]->MapkafromListl=Map(AVL.genAsTreemcmpl)-- | The union of a list of maps:-- (@'unions' == 'Prelude.foldl' 'union' 'empty'@).unions::Ordk=>[Mapka]->Mapkaunionsts=foldlStrictunionemptyts-- | The union of a list of maps, with a combining operation:-- (@'unionsWith' f == 'Prelude.foldl' ('unionWith' f) 'empty'@).unionsWith::Ordk=>(a->a->a)->[Mapka]->MapkaunionsWithfts=foldlStrict(unionWithf)emptyts-- | /O(n+m)/.-- The expression (@'union' t1 t2@) takes the left-biased union of @t1@ and @t2@.-- It prefers @t1@ when duplicate keys are encountered,-- i.e. (@'union' == 'unionWith' 'const'@).-- The implementation uses the efficient /hedge-union/ algorithm.-- Hedge-union is more efficient on (bigset `union` smallset)?union::Ordk=>Mapka->Mapka->Mapkaunion=unionWithconst-- | /O(n+m)/. Union with a combining function. unionWith::Ordk=>(a->a->a)->Mapka->Mapka->MapkaunionWithf=unionWithKey(\_xy->fxy)-- | /O(n+m)/.-- Union with a combining function. unionWithKey::Ordk=>(k->a->a->a)->Mapka->Mapka->MapkaunionWithKeyf(Mapt1)(Mapt2)=Map(AVL.genUnion(mfcmpf)t1t2)-- | /O(n+m)/.-- This function is defined as (@'isSubmapOf' = 'isSubmapOfBy' (==)@).isSubmapOf::(Ordk,Eqa)=>Mapka->Mapka->BoolisSubmapOf=isSubmapOfBy(==){- | /O(n+m)/.
The expression (@'isSubmapOfBy' f t1 t2@) returns 'True' if
all keys in @t1@ are in tree @t2@, and when @f@ returns 'True' when
applied to their respective values. For example, the following
expressions are all 'True':
> isSubmapOfBy (==) (fromList [('a',1)]) (fromList [('a',1),('b',2)])
> isSubmapOfBy (<=) (fromList [('a',1)]) (fromList [('a',1),('b',2)])
> isSubmapOfBy (==) (fromList [('a',1),('b',2)]) (fromList [('a',1),('b',2)])
But the following are all 'False':
> isSubmapOfBy (==) (fromList [('a',2)]) (fromList [('a',1),('b',2)])
> isSubmapOfBy (<) (fromList [('a',1)]) (fromList [('a',1),('b',2)])
> isSubmapOfBy (==) (fromList [('a',1),('b',2)]) (fromList [('a',1)])
-}isSubmapOfBy::Ordk=>(a->b->Bool)->Mapka->Mapkb->BoolisSubmapOfByf(Maps)(Mapt)=AVL.genIsSubsetOf(\(k,a)(k',b)->casecomparekk'ofLT->LTGT->GTEQ->iffabthenEQelseLT)st-- | /O(log n)/. The expression (@'alter' f k map@) alters the value @x@ at @k@, or absence thereof.-- 'alter' can be used to insert, delete, or update a value in a 'Map'.-- In short : @'lookup' k ('alter' f k m) = f ('lookup' k m)@alter::Ordk=>(Maybea->Maybea)->k->Mapka->Mapkaalterfkm=casef(lookupkm)ofJusta->insertkamNothing->deletekm-- TODO: add support for this in Data.Tree.AVL-- | /O(log n)/. Adjust a value at a specific key. When the key is not-- a member of the map, the original map is returned.adjust::Ordk=>(a->a)->k->Mapka->Mapkaadjustf=adjustWithKey(\_x->fx)-- | /O(log n)/. Adjust a value at a specific key. When the key is not-- a member of the map, the original map is returned.adjustWithKey::Ordk=>(k->a->a)->k->Mapka->MapkaadjustWithKeyf=updateWithKey(\kx->Just(fkx))-- | /O(log n)/. The expression (@'update' f k map@) updates the value @x@-- at @k@ (if it is in the map). If (@f x@) is 'Nothing', the element is-- deleted. If it is (@'Just' y@), the key @k@ is bound to the new value @y@.update::Ordk=>(a->Maybea)->k->Mapka->Mapkaupdatef=updateWithKey(\_x->fx)-- | /O(log n)/. The expression (@'updateWithKey' f k map@) updates the-- value @x@ at @k@ (if it is in the map). If (@f k x@) is 'Nothing',-- the element is deleted. If it is (@'Just' y@), the key @k@ is bound-- to the new value @y@.updateWithKey::Ordk=>(k->a->Maybea)->k->Mapka->MapkaupdateWithKeyfk(Mapt)=letcc(k',a)=casecomparekk'ofLT->COrdering.LtEQ->COrdering.Eq$fmap(\c->(k',c))$fk'aGT->COrdering.GtinMap(AVL.genDelMaybecct)-- | /O(log n)/. Lookup and update.---- TODO: only one traversal. This requires fiddling with AVL.Push.updateLookupWithKey::Ordk=>(k->a->Maybea)->k->Mapka->(Maybea,Mapka)updateLookupWithKeyfkm=(lookupkm,updateWithKeyfkm)-- | /O(n*log n)/. Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.fromListWith::Ordk=>(a->a->a)->[(k,a)]->MapkafromListWithfxs=fromListWithKey(\_kxy->fxy)xs-- | /O(n*log n)/. Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWithKey'.fromListWithKey::Ordk=>(k->a->a->a)->[(k,a)]->MapkafromListWithKeyfxs=foldlStrictinsemptyxswhereinst(k,x)=insertWithKeyfkxt-------------------------------- Conversion from/to raw tree.-- | /O(1)/. Convert a /sorted/ AVL tree to an AVL tree based Set (as provided by this module).-- This function does not check the input AVL tree is sorted.{-# INLINE unsafeFromTree #-}unsafeFromTree::AVL.AVL(k,a)->MapkaunsafeFromTree=Map-- | /O(1)/. Convert an AVL tree based Set (as provided by this module) to a sorted AVL tree.{-# INLINE toTree #-}toTree::Mapka->AVL.AVL(k,a)toTree(Mapt)=t------------------------------- InstancesinstanceFoldable(Mapk)wherefoldMapf(Mapt)=foldMap(f.snd)tinstanceOrdk=>Monoid(Mapka)wheremempty=emptymappend=unioninstanceFunctor(Mapk)wherefmapf(Mapt)=Map(fmapf't)wheref'(k,a)=(k,fa)--------------------------------------------------- UtilitiesfoldlStrict::(a->b->a)->a->[b]->afoldlStrictfzxs=casexsof[]->z(x:xx)->letz'=fzxinseqz'(foldlStrictfz'xx)