-- File created: 2008-11-08 15:52:33{-# LANGUAGE CPP, MultiParamTypeClasses, FlexibleInstances
, FlexibleContexts, UndecidableInstances #-}#include "exports.h"-- | The base implementation of a trie representing a set of lists, generalized-- over any type of map from key values to tries.---- Worst-case complexities are given in terms of @n@, @m@, and @k@. @n@ refers-- to the number of keys in the set and @m@ to their maximum length. @k@ refers-- to the length of a key given to the function, not any property of the set.---- In addition, the trie's branching factor plays a part in almost every-- operation, but the complexity depends on the underlying 'Map'. Thus, for-- instance, 'member' is actually @O(m f(b))@ where @f(b)@ is the complexity of-- a lookup operation on the 'Map' used. This complexity depends on the-- underlying operation, which is not part of the specification of the visible-- function. Thus it could change whilst affecting the complexity only for-- certain Map types: hence this \"b factor\" is not shown explicitly.---- Disclaimer: the complexities have not been proven.moduleData.ListTrie.Set(SET_EXPORTS)whereimportControl.Arrow((***))importControl.Monad(liftM2)importData.Binary(Binary,get,put)importData.Function(on)importData.Monoid(Monoid(..))importPreludehiding(filter,foldl,foldr,map,null)importqualifiedPrelude#if __GLASGOW_HASKELL__importText.Read(readPrec,lexP,parens,prec,Lexeme(Ident))#endifimportqualifiedData.ListTrie.BaseasBaseimportqualifiedData.ListTrie.Base.MapasMapimportData.ListTrie.Base.Classes(Identity(..),Unwrappable(..))importData.ListTrie.Base.Map(Map,OrdMap)importData.ListTrie.Util((.:),(.:.),both)#include "docs.h"-- Invariant: any (Tr False _) has a True descendant.---- We need this 'bool' and Base stuff in order to satisfy the Base.Trie type-- class.dataTrieSetBasemapabool=Tr!bool!(CMapmapabool)typeCMapmapabool=mapa(TrieSetBasemapabool)-- That makes TrieSet a newtype, which means some unfortunate wrapping and-- unwrapping in the function definitions below.---- | The data structure itself: a set of keys of type @[a]@ implemented as a-- trie, using @map@ to map keys of type @a@ to sub-tries.---- Regarding the instances:---- - The @CMap@ type is internal, ignore it. For 'Eq' and 'Ord' an 'Eq'-- instance is required: what this means is that @map a v@ is expected to be-- an instance of 'Eq', given 'Eq'@ v@.---- - The 'Eq' constraint for the 'Ord' instance is misleading: it is needed-- only because 'Eq' is a superclass of 'Ord'.---- - The 'Monoid' instance defines 'mappend' as 'union' and 'mempty' as-- 'empty'.newtypeTrieSetmapa=TS{unTS::TrieSetBasemapaBool}inTS::(TrieSetBasemapaBool->TrieSetBasenapbBool)->(TrieSetmapa->TrieSetnapb)inTSf=TS.f.unTSinstanceMapmapk=>Base.TrieTrieSetBaseIdentitymapkwheremkTrie=Tr.unwraptParts(Trbm)=(Idb,m)-- CMap contains TrieSetBase, not TrieSet, hence we must supply these instances-- for TrieSetBase firstinstanceEq(CMapmapaBool)=>Eq(TrieSetBasemapaBool)whereTrb1m1==Trb2m2=b1==b2&&m1==m2instance(Eq(CMapmapaBool),OrdMapmapa,Orda)=>Ord(TrieSetBasemapaBool)wherecompare=compare`on`Base.toAscListinstanceEq(CMapmapaBool)=>Eq(TrieSetmapa)where(==)=(==)`on`unTS-- The CMap constraint is needed only because Eq is a superclass of Ord....-- sighinstance(Eq(CMapmapaBool),OrdMapmapa,Orda)=>Ord(TrieSetmapa)wherecompare=compare`on`unTSinstanceMapmapa=>Monoid(TrieSetmapa)wheremempty=emptymappend=unionmconcat=unionsinstance(Mapmapa,Showa)=>Show(TrieSetmapa)whereshowsPrecps=showParen(p>10)$showString"fromList ".shows(toLists)instance(Mapmapa,Reada)=>Read(TrieSetmapa)where#if __GLASGOW_HASKELL__readPrec=parens$prec10$doIdent"fromList"<-lexPfmapfromListreadPrec#elsereadsPrecp=readParen(p>10)$\r->do("fromList",list)<-lexr(xs,rest)<-readsPrec(p+1)list[(fromListxs,rest)]#endifinstance(Mapmapk,Binaryk,Binarya)=>Binary(TrieSetBasemapka)whereput(Trvm)=putv>>(put.Map.serializeToList$m)get=liftM2Trget(get>>=return.Map.deserializeFromList)instance(Mapmapa,Binarya)=>Binary(TrieSetmapa)whereput=put.unTSget=get>>=return.TS-- * Construction-- | @O(1)@. The empty set.empty::Mapmapa=>TrieSetmapaempty=TSBase.empty-- | @O(s)@. The singleton set containing only the given key.singleton::Mapmapa=>[a]->TrieSetmapasingletonk=TS$Base.singletonkTrue-- * Modification-- | @O(min(m,s))@. Inserts the key into the set. If the key is already a-- member of the set, the set is unchanged.insert::Mapmapa=>[a]->TrieSetmapa->TrieSetmapainsertk=inTS$Base.insertkTrue-- | @O(min(m,s))@. Removes the key from the set. If the key is not a member of-- the set, the set is unchanged.delete::Mapmapa=>[a]->TrieSetmapa->TrieSetmapadelete=inTS.Base.delete-- * Querying-- | @O(1)@. 'True' iff the set is empty.null::Mapmapa=>TrieSetmapa->Boolnull=Base.null.unTS-- | @O(n m)@. The number of keys in the set. The value is built up lazily,-- allowing for delivery of partial results without traversing the whole set.size::(Mapmapa,Numn)=>TrieSetmapa->nsize=Base.size.unTS-- | @O(n m)@. The number of keys in the set. The value is built strictly: no-- value is returned until the set has been fully traversed.size'::(Mapmapa,Numn)=>TrieSetmapa->nsize'=Base.size'.unTS-- | @O(min(m,s))@. 'True' iff the given key is contained within the set.member::Mapmapa=>[a]->TrieSetmapa->Boolmember=Base.member.:.unTS-- | @O(min(m,s))@. 'False' iff the given key is contained within the set.notMember::Mapmapa=>[a]->TrieSetmapa->BoolnotMember=Base.notMember.:.unTS-- | @O(min(n1 m1,n2 m2))@. 'True' iff the first set is a subset of the second,-- i.e. all keys that are members of the first set are also members of the-- second set.isSubsetOf::Mapmapa=>TrieSetmapa->TrieSetmapa->BoolisSubsetOf=Base.isSubmapOfBy(&&)`on`unTS-- | @O(min(n1 m1,n2 m2))@. 'True' iff the first set is a proper subset of the-- second, i.e. the first is a subset of the second, but the sets are not-- equal.isProperSubsetOf::Mapmapa=>TrieSetmapa->TrieSetmapa->BoolisProperSubsetOf=Base.isProperSubmapOfBy(&&)`on`unTS-- * CombinationdefaultUnion::Bool->Bool->BooldefaultUnion=error"TrieSet.union :: internal error"-- | @O(min(n1 m1,n2 m2))@. The union of the two sets: the set which contains-- all keys that are members of either set.---- The worst-case performance occurs when the two sets are identical.union::Mapmapa=>TrieSetmapa->TrieSetmapa->TrieSetmapaunion=TS.:Base.unionWithdefaultUnion`on`unTS-- | @O(sum(n))@. The union of all the sets: the set which contains all keys-- that are members of any of the sets.---- The worst-case performance occurs when all the sets are identical.unions::Mapmapa=>[TrieSetmapa]->TrieSetmapaunions=TS.Base.unionsWithdefaultUnion.Prelude.mapunTS-- | @O(min(n1 m1,n2 m2))@. The difference of the two sets: the set which-- contains all keys that are members of the first set and not members of the-- second set.---- The worst-case performance occurs when the two sets are identical.difference::Mapmapa=>TrieSetmapa->TrieSetmapa->TrieSetmapadifference=TS.:Base.differenceWith(error"TrieSet.difference :: internal error")`on`unTS-- | @O(min(n1 m1,n2 m2))@. The intersection of the two sets: the set which-- contains all keys that are members of both sets.---- The worst-case performance occurs when the two sets are identical.intersection::Mapmapa=>TrieSetmapa->TrieSetmapa->TrieSetmapaintersection=TS.:Base.intersectionWith(error"TrieSet.intersection :: internal error")`on`unTS-- * Filtering-- | @O(n m)@. The set of those keys in the set for which the given predicate-- returns 'True'.filter::Mapmapa=>([a]->Bool)->TrieSetmapa->TrieSetmapafilterp=inTS$Base.filterWithKey(\k_->pk)-- | @O(n m)@. A pair of sets: the first element contains those keys for which-- the given predicate returns 'True', and the second element contains those-- for which it was 'False'.partition::Mapmapa=>([a]->Bool)->TrieSetmapa->(TrieSetmapa,TrieSetmapa)partitionp=bothTS.Base.partitionWithKey(\k_->pk).unTS-- * Mapping-- | @O(n m)@. Apply the given function to all the keys in the set.map::(Mapmapa,Mapmapb)=>([a]->[b])->TrieSetmapa->TrieSetmapbmap=inTS.Base.mapKeysWithBase.fromList-- | @O(n m)@. Apply the given function to the contents of all the keys in the-- set.mapIn::(Mapmapa,Mapmapb)=>(a->b)->TrieSetmapa->TrieSetmapbmapIn=inTS.Base.mapInKeysWithdefaultUnion-- * Folding-- | @O(n m)@. Equivalent to a list @foldr@ on the 'toList' representation.foldr::Mapmapa=>([a]->b->b)->b->TrieSetmapa->bfoldrf=Base.foldrWithKey(\k_->fk).:.unTS-- | @O(n m)@. Equivalent to a list @foldr@ on the 'toAscList' representation.foldrAsc::OrdMapmapa=>([a]->b->b)->b->TrieSetmapa->bfoldrAscf=Base.foldrAscWithKey(\k_->fk).:.unTS-- | @O(n m)@. Equivalent to a list @foldr@ on the 'toDescList' representation.foldrDesc::OrdMapmapa=>([a]->b->b)->b->TrieSetmapa->bfoldrDescf=Base.foldrDescWithKey(\k_->fk).:.unTS-- | @O(n m)@. Equivalent to a list @foldl@ on the 'toList' representation.foldl::Mapmapa=>([a]->b->b)->b->TrieSetmapa->bfoldlf=Base.foldlWithKey(\k_->fk).:.unTS-- | @O(n m)@. Equivalent to a list @foldl@ on the 'toAscList' representation.foldlAsc::OrdMapmapa=>([a]->b->b)->b->TrieSetmapa->bfoldlAscf=Base.foldlAscWithKey(\k_->fk).:.unTS-- | @O(n m)@. Equivalent to a list @foldl@ on the 'toDescList' representation.foldlDesc::OrdMapmapa=>([a]->b->b)->b->TrieSetmapa->bfoldlDescf=Base.foldlDescWithKey(\k_->fk).:.unTS-- | @O(n m)@. Equivalent to a list @foldl'@ on the 'toList' representation.foldl'::Mapmapa=>([a]->b->b)->b->TrieSetmapa->bfoldl'f=Base.foldlWithKey'(\k_->fk).:.unTS-- | @O(n m)@. Equivalent to a list @foldl'@ on the 'toAscList' representation.foldlAsc'::OrdMapmapa=>([a]->b->b)->b->TrieSetmapa->bfoldlAsc'f=Base.foldlAscWithKey'(\k_->fk).:.unTS-- | @O(n m)@. Equivalent to a list @foldl'@ on the 'toDescList'-- representation.foldlDesc'::OrdMapmapa=>([a]->b->b)->b->TrieSetmapa->bfoldlDesc'f=Base.foldlDescWithKey'(\k_->fk).:.unTS-- * Conversion between lists-- | @O(n m)@. Converts the set to a list of the keys contained within, in-- undefined order.toList::Mapmapa=>TrieSetmapa->[[a]]toList=Prelude.mapfst.Base.toList.unTS-- | @O(n m)@. Converts the set to a list of the keys contained within, in-- ascending order.toAscList::OrdMapmapa=>TrieSetmapa->[[a]]toAscList=Prelude.mapfst.Base.toAscList.unTS-- | @O(n m)@. Converts the set to a list of the keys contained within, in-- descending order.toDescList::OrdMapmapa=>TrieSetmapa->[[a]]toDescList=Prelude.mapfst.Base.toDescList.unTS-- | @O(n m)@. Creates a set from a list of keys.fromList::Mapmapa=>[[a]]->TrieSetmapafromList=TS.Base.fromList.Prelude.map(flip(,)True)-- * Ordering ops-- | @O(m)@. Removes and returns the minimal key in the set. If the set is-- empty, 'Nothing' and the original set are returned.minView::OrdMapmapa=>TrieSetmapa->(Maybe[a],TrieSetmapa)minView=(fmapfst***TS).Base.minView.unTS-- | @O(m)@. Removes and returns the maximal key in the set. If the set is-- empty, 'Nothing' and the original set are returned.maxView::OrdMapmapa=>TrieSetmapa->(Maybe[a],TrieSetmapa)maxView=(fmapfst***TS).Base.maxView.unTS-- | @O(m)@. Like 'fst' composed with 'minView'. 'Just' the minimal key in the-- set, or 'Nothing' if the set is empty.findMin::OrdMapmapa=>TrieSetmapa->Maybe[a]findMin=fmapfst.Base.findMin.unTS-- | @O(m)@. Like 'fst' composed with 'maxView'. 'Just' the maximal key in the-- set, or 'Nothing' if the set is empty.findMax::OrdMapmapa=>TrieSetmapa->Maybe[a]findMax=fmapfst.Base.findMax.unTS-- | @O(m)@. Like 'snd' composed with 'minView'. The set without its minimal-- key, or the unchanged original set if it was empty.deleteMin::OrdMapmapa=>TrieSetmapa->TrieSetmapadeleteMin=inTSBase.deleteMin-- | @O(m)@. Like 'snd' composed with 'maxView'. The set without its maximal-- key, or the unchanged original set if it was empty.deleteMax::OrdMapmapa=>TrieSetmapa->TrieSetmapadeleteMax=inTSBase.deleteMax-- | @O(min(m,s))@. Splits the set in two about the given key. The first-- element of the resulting pair is a set containing the keys lesser than the-- given key; the second contains those keys that are greater.split::OrdMapmapa=>[a]->TrieSetmapa->(TrieSetmapa,TrieSetmapa)split=bothTS.:Base.split.:.unTS-- | @O(min(m,s))@. Like 'split', but also returns whether the given key was a-- member of the set or not.splitMember::OrdMapmapa=>[a]->TrieSetmapa->(TrieSetmapa,Bool,TrieSetmapa)splitMember=(\(l,b,g)->(TSl,unwrapb,TSg)).:Base.splitLookup.:.unTS-- | @O(m)@. 'Just' the key of the set which precedes the given key in order,-- or 'Nothing' if the set is empty.findPredecessor::OrdMapmapa=>[a]->TrieSetmapa->Maybe[a]findPredecessor=fmapfst.:Base.findPredecessor.:.unTS-- | @O(m)@. 'Just' the key of the set which succeeds the given key in order,-- or 'Nothing' if the set is empty.findSuccessor::OrdMapmapa=>[a]->TrieSetmapa->Maybe[a]findSuccessor=fmapfst.:Base.findSuccessor.:.unTS-- * Trie-only operations-- | @O(s)@. Prepends the given key to all the keys of the set. For example:---- > addPrefix "pre" (fromList ["a","b"]) == fromList ["prea","preb"]addPrefix::Mapmapa=>[a]->TrieSetmapa->TrieSetmapaaddPrefix=TS.:Base.addPrefix.:.unTS-- | @O(m)@. The set which contains all keys of which the given key is a-- prefix, with the prefix removed from each key. If the given key is not a-- prefix of any key in the set, an empty set is returned. For example:---- > deletePrefix "a" (fromList ["a","ab","ac"]) == fromList ["","b","c"]---- This function can be used, for instance, to reduce potentially expensive I/O-- operations: if you need to check whether a string is a member of a set, but-- you only have a prefix of it and retrieving the rest is an expensive-- operation, calling 'deletePrefix' with what you have might allow you to-- avoid the operation: if the resulting set is empty, the entire string cannot-- be a member of the set.deletePrefix::Mapmapa=>[a]->TrieSetmapa->TrieSetmapadeletePrefix=TS.:Base.deletePrefix.:.unTS-- | @O(m)@. A triple containing the longest common prefix of all keys in the-- set, whether that prefix was a member of the set, and the set with that-- prefix removed from all the keys as well as the set itself. Examples:---- > splitPrefix (fromList ["a","b"]) == ("", False, fromList ["a","b"])-- > splitPrefix (fromList ["a","ab","ac"]) == ("a", True, fromList ["b","c"])splitPrefix::Mapmapa=>TrieSetmapa->([a],Bool,TrieSetmapa)splitPrefix=(\(k,b,t)->(k,unwrapb,TSt)).Base.splitPrefix.unTS-- | @O(m)@. The children of the longest common prefix in the trie as sets,-- associated with their distinguishing key value. If the set contains less-- than two keys, this function will return an empty map. Examples;---- > children (fromList ["a","abc","abcd"])-- > == Map.fromList [('b',fromList ["c","cd"])]-- > children (fromList ["b","c"])-- > == Map.fromList [('b',fromList [""]),('c',fromList [""])]children::Mapmapa=>TrieSetmapa->mapa(TrieSetmapa)children=Map.mapTS.Base.children.unTS-- | @O(1)@. The children of the first element of the longest common prefix in-- the trie as sets, associated with their distinguishing key value. If the set-- contains less than two keys, this function will return an empty map.---- If the longest common prefix of all keys in the trie is the empty list, this-- function is equivalent to 'children'. Otherwise, the result will always be a-- single-element map.---- Examples:---- > children1 (fromList ["abc","abcd"])-- > == Map.fromList [('a',fromList ["bc","bcd"])]-- > children1 (fromList ["b","c"])-- > == Map.fromList [('b',fromList [""]),('c',fromList [""])]children1::Mapmapa=>TrieSetmapa->mapa(TrieSetmapa)children1=Map.mapTS.Base.children1.unTS-- * Visualization-- | @O(n m)@. Displays the set's internal structure in an undefined way. That-- is to say, no program should depend on the function's results.showTrie::(Showa,Mapmapa)=>TrieSetmapa->ShowSshowTrie=Base.showTrieWith(\(Idb)->showChar$ifbthen'X'else' ').unTS