{-# LANGUAGE BangPatterns, CPP #-}-------------------------------------------------------------------------- |-- Module : Data.HashMap.Lazy-- Copyright : 2010-2011 Johan Tibell-- License : BSD-style-- Maintainer : johan.tibell@gmail.com-- Stability : provisional-- Portability : portable---- A map from /hashable/ keys to values. A map cannot contain-- duplicate keys; each key can map to at most one value. A 'HashMap'-- makes no guarantees as to the order of its elements.---- This map is strict in the keys and lazy in the values; keys are-- evaluated to /weak head normal form/ before they are added to the-- map.---- The implementation is based on /big-endian patricia trees/, keyed-- by a hash of the original key. A 'HashMap' is often faster than-- other tree-based maps, especially when key comparison is expensive,-- as in the case of strings.---- Many operations have a worst-case complexity of /O(min(n,W))/.-- This means that the operation can become linear in the number of-- elements with a maximum of /W/ -- the number of bits in an 'Int'-- (32 or 64).moduleData.HashMap.Lazy(HashMap-- * Construction,empty,singleton-- * Basic interface,null,size,lookup,lookupDefault,insert,delete,insertWith,adjust-- * Combine-- ** Union,union-- * Transformations,map,traverseWithKey-- * Difference and intersection,difference,intersection-- * Folds,foldl',foldlWithKey',foldr,foldrWithKey-- * Filter,filter,filterWithKey-- * Conversions,elems,keys-- ** Lists,toList,fromList,fromListWith)whereimportqualifiedData.FullList.LazyasFLimportData.Hashable(Hashable(hash))importqualifiedData.ListasListimportPreludehiding(filter,foldr,lookup,map,null,pred)importData.HashMap.Common-------------------------------------------------------------------------- * Basic interface-- | /O(1)/ Return 'True' if this map is empty, 'False' otherwise.null::HashMapkv->BoolnullNil=Truenull_=False-- | /O(n)/ Return the number of key-value mappings in this map.size::HashMapkv->Intsizet=got0wherego(Bin_lr)!sz=gor(golsz)go(Tip_l)!sz=sz+FL.sizelgoNil!sz=sz-- | /O(min(n,W))/ Return the value to which the specified key is-- mapped, or 'Nothing' if this map contains no mapping for the key.lookup::(Eqk,Hashablek)=>k->HashMapkv->Maybevlookupk0t=goh0k0twhereh0=hashk0go!h!k(Binsmlr)|zerohsm=gohkl|otherwise=gohkrgohk(Tiph'l)|h==h'=FL.lookupkl|otherwise=Nothinggo__Nil=Nothing#if __GLASGOW_HASKELL__ >= 700{-# INLINABLE lookup #-}#endif-- | /O(min(n,W))/ Return the value to which the specified key is-- mapped, or the default value if this map contains no mapping for-- the key.lookupDefault::(Eqk,Hashablek)=>v-- ^ Default value to return.->k->HashMapkv->vlookupDefaultdefkt=caselookupktofJustv->v_->def{-# INLINE lookupDefault #-}-- | /O(1)/ Construct a map with a single element.singleton::Hashablek=>k->v->HashMapkvsingletonkv=Tiph$FL.singletonkvwhereh=hashk#if __GLASGOW_HASKELL__ >= 700{-# INLINABLE singleton #-}#endif-- | /O(min(n,W))/ Associate the specified value with the specified-- key in this map. If this map previously contained a mapping for-- the key, the old value is replaced.insert::(Eqk,Hashablek)=>k->v->HashMapkv->HashMapkvinsertk0v0t0=goh0k0v0t0whereh0=hashk0go!h!kvt@(Binsmlr)|nomatchhsm=joinh(Tiph$FL.singletonkv)smt|zerohsm=Binsm(gohkvl)r|otherwise=Binsml(gohkvr)gohkvt@(Tiph'l)|h==h'=Tiph$FL.insertkvl|otherwise=joinh(Tiph$FL.singletonkv)h'tgohkvNil=Tiph$FL.singletonkv#if __GLASGOW_HASKELL__ >= 700{-# INLINABLE insert #-}#endif-- | /O(min(n,W))/ Remove the mapping for the specified key from this-- map if present.delete::(Eqk,Hashablek)=>k->HashMapkv->HashMapkvdeletek0=goh0k0whereh0=hashk0go!h!kt@(Binsmlr)|nomatchhsm=t|zerohsm=binsm(gohkl)r|otherwise=binsml(gohkr)gohkt@(Tiph'l)|h==h'=caseFL.deleteklofNothing->NilJustl'->Tiph'l'|otherwise=tgo__Nil=Nil#if __GLASGOW_HASKELL__ >= 700{-# INLINABLE delete #-}#endif-- | /O(min(n,W))/ Associate the value with the key in this map. If-- this map previously contained a mapping for the key, the old value-- is replaced by the result of applying the given function to the new-- and old value. Example:---- > insertWith f k v map-- > where f new old = new + oldinsertWith::(Eqk,Hashablek)=>(v->v->v)->k->v->HashMapkv->HashMapkvinsertWithfk0v0t0=goh0k0v0t0whereh0=hashk0go!h!kvt@(Binsmlr)|nomatchhsm=joinh(Tiph$FL.singletonkv)smt|zerohsm=Binsm(gohkvl)r|otherwise=Binsml(gohkvr)gohkvt@(Tiph'l)|h==h'=Tiph$FL.insertWithfkvl|otherwise=joinh(Tiph$FL.singletonkv)h'tgohkvNil=Tiph$FL.singletonkv#if __GLASGOW_HASKELL__ >= 700{-# INLINABLE insertWith #-}#endif-- | /O(min(n,W)/ Adjust the value tied to a given key in this map-- only if it is present. Otherwise, leave the map alone.adjust::(Eqk,Hashablek)=>(v->v)->k->HashMapkv->HashMapkvadjustfk0t0=goh0k0t0whereh0=hashk0go!h!kt@(Binsmlr)|nomatchhsm=t|zerohsm=Binsm(gohkl)r|otherwise=Binsml(gohkr)gohkt@(Tiph'l)|h==h'=Tiph$FL.adjustfkl|otherwise=tgo__Nil=Nil#if __GLASGOW_HASKELL__ >= 700{-# INLINABLE adjust #-}#endif-------------------------------------------------------------------------- * Transformations-- | /O(n)/ Transform this map by applying a function to every value.map::(v1->v2)->HashMapkv1->HashMapkv2mapf=gowherego(Binsmlr)=Binsm(gol)(gor)go(Tiphl)=Tiph(FL.mapf'l)goNil=Nilf'kv=(k,fv){-# INLINE map #-}-- | /O(n)/ Difference of two maps. Return elements of the first map-- not existing in the second.difference::(Eqk,Hashablek)=>HashMapkv->HashMapkw->HashMapkvdifferenceab=foldlWithKey'goemptyawheregomkv=caselookupkbofNothing->insertkvm_->m#if __GLASGOW_HASKELL__ >= 700{-# INLINABLE difference #-}#endif-- | /O(n)/ Intersection of two maps. Return elements of the first map-- for keys existing in the second.intersection::(Eqk,Hashablek)=>HashMapkv->HashMapkw->HashMapkvintersectionab=foldlWithKey'goemptyawheregomkv=caselookupkbofJust_->insertkvm_->m#if __GLASGOW_HASKELL__ >= 700{-# INLINABLE intersection #-}#endif-------------------------------------------------------------------------- * Folds-- | /O(n)/ Reduce this map by applying a binary operator to all-- elements, using the given starting value (typically the-- right-identity of the operator).foldr::(v->a->a)->a->HashMapkv->afoldrf=foldrWithKey(constf){-# INLINE foldr #-}-- | /O(n)/ Reduce this map by applying a binary operator to all-- elements, using the given starting value (typically the-- left-identity of the operator). Each application of the operator-- is evaluated before before using the result in the next-- application. This function is strict in the starting value.foldl'::(a->v->a)->a->HashMapkv->afoldl'f=foldlWithKey'(\z_v->fzv){-# INLINE foldl' #-}-- | /O(n)/ Reduce this map by applying a binary operator to all-- elements, using the given starting value (typically the-- left-identity of the operator). Each application of the operator-- is evaluated before before using the result in the next-- application. This function is strict in the starting value.foldlWithKey'::(a->k->v->a)->a->HashMapkv->afoldlWithKey'f=gowherego!z(Bin_lr)=letz'=gozlinz'`seq`goz'rgoz(Tip_l)=FL.foldlWithKey'fzlgozNil=z{-# INLINE foldlWithKey' #-}-------------------------------------------------------------------------- * Filter-- | /O(n)/ Filter this map by retaining only elements satisfying a-- predicate.filterWithKey::(k->v->Bool)->HashMapkv->HashMapkvfilterWithKeypred=gowherego(Binsmlr)=binsm(gol)(gor)go(Tiphl)=caseFL.filterWithKeypredlofJustl'->Tiphl'Nothing->NilgoNil=Nil{-# INLINE filterWithKey #-}-- | /O(n)/ Filter this map by retaining only elements which values-- satisfy a predicate.filter::(v->Bool)->HashMapkv->HashMapkvfilterp=filterWithKey(\_v->pv){-# INLINE filter #-}-------------------------------------------------------------------------- Conversions-- | /O(n*min(W, n))/ Construct a map from a list of elements.fromList::(Eqk,Hashablek)=>[(k,v)]->HashMapkvfromList=List.foldl'(\m(k,v)->insertkvm)empty{-# INLINE fromList #-}-- | /O(n*min(W, n))/ Construct a map from a list of elements. Uses-- the provided function to merge duplicate entries.fromListWith::(Eqk,Hashablek)=>(v->v->v)->[(k,v)]->HashMapkvfromListWithf=List.foldl'(\m(k,v)->insertWithfkvm)empty{-# INLINE fromListWith #-}-- | /O(n)/ Return a list of this map's keys. The list is produced-- lazily.keys::HashMapkv->[k]keys=List.mapfst.toList{-# INLINE keys #-}-- | /O(n)/ Return a list of this map's values. The list is produced-- lazily.elems::HashMapkv->[v]elems=List.mapsnd.toList{-# INLINE elems #-}