generic-trie 0.1 → 0.2
raw patch · 2 files changed
+440/−103 lines, 2 filesdep +transformersPVP ok
version bump matches the API change (PVP)
Dependencies added: transformers
API changes (from Hackage documentation)
- Data.GenericTrie: gtrieFold :: GTrieKey f => (a -> b -> b) -> GTrie f a -> b -> b
- Data.GenericTrie: trieFold :: TrieKey k => (a -> b -> b) -> Trie k a -> b -> b
+ Data.GenericTrie: OrdKey :: k -> OrdKey k
+ Data.GenericTrie: difference :: TrieKey k => Trie k a -> Trie k b -> Trie k a
+ Data.GenericTrie: differenceWith :: TrieKey k => (a -> b -> Maybe a) -> Trie k a -> Trie k b -> Trie k a
+ Data.GenericTrie: differenceWithKey :: TrieKey k => (k -> a -> b -> Maybe a) -> Trie k a -> Trie k b -> Trie k a
+ Data.GenericTrie: foldWithKey :: TrieKey k => (k -> a -> r -> r) -> r -> Trie k a -> r
+ Data.GenericTrie: genericDelete :: (GTrieKey (Rep k), Generic k, TrieRep k ~ TrieRepDefault k) => k -> Trie k a -> Trie k a
+ Data.GenericTrie: genericEmpty :: TrieRep k ~ TrieRepDefault k => Trie k a
+ Data.GenericTrie: genericFoldWithKey :: (GTrieKey (Rep k), Generic k, TrieRep k ~ TrieRepDefault k) => (k -> a -> r -> r) -> r -> Trie k a -> r
+ Data.GenericTrie: genericInsert :: (GTrieKey (Rep k), Generic k, TrieRep k ~ TrieRepDefault k) => k -> a -> Trie k a -> Trie k a
+ Data.GenericTrie: genericLookup :: (GTrieKey (Rep k), Generic k, TrieRep k ~ TrieRepDefault k) => k -> Trie k a -> Maybe a
+ Data.GenericTrie: genericMapMaybeWithKey :: (GTrieKey (Rep k), Generic k, TrieRep k ~ TrieRepDefault k) => (k -> a -> Maybe b) -> Trie k a -> Trie k b
+ Data.GenericTrie: genericSingleton :: (GTrieKey (Rep k), Generic k, TrieRep k ~ TrieRepDefault k) => k -> a -> Trie k a
+ Data.GenericTrie: genericTraverseWithKey :: (GTrieKey (Rep k), Generic k, TrieRep k ~ TrieRepDefault k, Applicative f) => (k -> a -> f b) -> Trie k a -> f (Trie k b)
+ Data.GenericTrie: genericTrieMap :: (GTrieKey (Rep k), TrieRep k ~ TrieRepDefault k) => (a -> b) -> Trie k a -> Trie k b
+ Data.GenericTrie: genericTrieNull :: TrieRep k ~ TrieRepDefault k => Trie k a -> Bool
+ Data.GenericTrie: genericTrieShowsPrec :: (Show a, GTrieKeyShow (Rep k), TrieRep k ~ TrieRepDefault k) => Int -> Trie k a -> ShowS
+ Data.GenericTrie: genericTrieTraverse :: (GTrieKey (Rep k), TrieRep k ~ TrieRepDefault k, Applicative f) => (a -> f b) -> Trie k a -> f (Trie k b)
+ Data.GenericTrie: getOrdKey :: OrdKey k -> k
+ Data.GenericTrie: gfoldWithKey :: GTrieKey f => (f p -> a -> r -> r) -> r -> GTrie f a -> r
+ Data.GenericTrie: gmapMaybeWithKey :: GTrieKey f => (f p -> a -> Maybe b) -> GTrie f a -> Maybe (GTrie f b)
+ Data.GenericTrie: gmergeWithKey :: GTrieKey f => (f p -> a -> b -> Maybe c) -> (GTrie f a -> Maybe (GTrie f c)) -> (GTrie f b -> Maybe (GTrie f c)) -> GTrie f a -> GTrie f b -> Maybe (GTrie f c)
+ Data.GenericTrie: gtraverseWithKey :: (GTrieKey f, Applicative m) => (f p -> a -> m b) -> GTrie f a -> m (GTrie f b)
+ Data.GenericTrie: instance GTrieKey f => Functor (GTrie f)
+ Data.GenericTrie: intersection :: TrieKey k => Trie k a -> Trie k b -> Trie k a
+ Data.GenericTrie: intersectionWith :: TrieKey k => (a -> b -> c) -> Trie k a -> Trie k b -> Trie k c
+ Data.GenericTrie: intersectionWithKey :: TrieKey k => (k -> a -> b -> c) -> Trie k a -> Trie k b -> Trie k c
+ Data.GenericTrie: mapMaybe :: TrieKey k => (a -> Maybe b) -> Trie k a -> Trie k b
+ Data.GenericTrie: mapMaybeWithKey :: TrieKey k => (k -> a -> Maybe b) -> Trie k a -> Trie k b
+ Data.GenericTrie: mergeWithKey :: TrieKey k => (k -> a -> b -> Maybe c) -> (Trie k a -> Trie k c) -> (Trie k b -> Trie k c) -> Trie k a -> Trie k b -> Trie k c
+ Data.GenericTrie: newtype OrdKey k
+ Data.GenericTrie: toList :: TrieKey k => Trie k a -> [(k, a)]
+ Data.GenericTrie: traverseWithKey :: (TrieKey k, Applicative f) => (k -> a -> f b) -> Trie k a -> f (Trie k b)
+ Data.GenericTrie: union :: TrieKey k => Trie k a -> Trie k a -> Trie k a
+ Data.GenericTrie: unionWith :: TrieKey k => (a -> a -> a) -> Trie k a -> Trie k a -> Trie k a
+ Data.GenericTrie: unionWithKey :: TrieKey k => (k -> a -> a -> a) -> Trie k a -> Trie k a -> Trie k a
- Data.GenericTrie: class TrieKey k where type family TrieRep k a type instance TrieRep k a = TrieRepDefault k a empty = MkTrie Nothing singleton k v = MkTrie $ Just $! gtrieSingleton (from k) v trieNull (MkTrie mb) = isNothing mb lookup k (MkTrie t) = gtrieLookup (from k) =<< t insert k v (MkTrie Nothing) = MkTrie (Just $! gtrieSingleton (from k) v) insert k v (MkTrie (Just t)) = MkTrie (Just $! gtrieInsert (from k) v t) delete _ t@(MkTrie Nothing) = t delete k (MkTrie (Just t)) = MkTrie (gtrieDelete (from k) t) trieMap f (MkTrie x) = MkTrie (fmap (gtrieMap f) $! x) trieFold f (MkTrie (Just x)) z = gtrieFold f x z trieFold _ (MkTrie Nothing) z = z trieTraverse f (MkTrie x) = fmap MkTrie (traverse (gtrieTraverse f) x) trieShowsPrec p (MkTrie (Just x)) = showsPrec p x trieShowsPrec _ (MkTrie Nothing) = showString "()"
+ Data.GenericTrie: class TrieKey k where type family TrieRep k :: * -> * type instance TrieRep k = TrieRepDefault k empty = genericEmpty singleton = genericSingleton trieNull = genericTrieNull lookup = genericLookup insert = genericInsert delete = genericDelete trieMap = genericTrieMap trieTraverse = genericTrieTraverse trieShowsPrec = genericTrieShowsPrec mapMaybeWithKey = genericMapMaybeWithKey foldWithKey = genericFoldWithKey traverseWithKey = genericTraverseWithKey mergeWithKey = genericMergeWithKey
- Data.GenericTrie: type TrieRepDefault k a = Maybe (GTrie (Rep k) a)
+ Data.GenericTrie: type TrieRepDefault k = Compose Maybe (GTrie (Rep k))
Files
- generic-trie.cabal +5/−4
- src/Data/GenericTrie.hs +435/−99
generic-trie.cabal view
@@ -1,12 +1,12 @@ name: generic-trie-version: 0.1+version: 0.2 synopsis: A map, where the keys may be complex structured data.-description: This type implements maps where the keys are themeselves- complexs strucutured data. For example, the keys may be+description: This type implements maps where the keys are themselves+ complex structured data. For example, the keys may be the abstract syntax trees for a programming language. The map is implemented as a trie, so common parts of the keys will be shared in the representation. The library- provides a generic implementation of the data strucutre,+ provides a generic implementation of the data structure, so values of types that have support for 'Generic' may be automatically used as keys in the map. license: BSD3@@ -22,6 +22,7 @@ library exposed-modules: Data.GenericTrie build-depends: base >= 4.5 && < 4.9,+ transformers >= 0.2 && < 0.5, containers >= 0.4.2.1 && < 0.6 GHC-options: -O2 -Wall
src/Data/GenericTrie.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UndecidableInstances #-} -- allows the TypeRep default {- | @@ -35,17 +36,44 @@ , member , notMember , fromList+ , toList+ , mapMaybe+ , union+ , unionWith+ , unionWithKey+ , intersection+ , intersectionWith+ , intersectionWithKey+ , difference+ , differenceWith+ , differenceWithKey , TrieKey(..)+ -- * Manual ord key instance selector+ , OrdKey(..) -- * Generic derivation implementation+ , genericTrieNull+ , genericTrieMap+ , genericTrieTraverse+ , genericTrieShowsPrec+ , genericInsert+ , genericLookup+ , genericDelete+ , genericMapMaybeWithKey+ , genericSingleton+ , genericEmpty+ , genericFoldWithKey+ , genericTraverseWithKey , TrieRepDefault , GTrieKey(..) , GTrie(..) ) where -import Control.Applicative (Applicative, liftA2, pure)-import Data.Char (ord)+import Control.Applicative (Applicative, liftA2)+import Data.Char (chr, ord)+import Data.Coerce (coerce) import Data.Foldable (Foldable)+import Data.Functor.Compose (Compose(..)) import Data.IntMap (IntMap) import Data.List (foldl') import Data.Map (Map)@@ -64,7 +92,7 @@ class TrieKey k where -- | Type of the representation of tries for this key.- type TrieRep k a+ type TrieRep k :: * -> * -- | Construct an empty trie empty :: Trie k a@@ -87,100 +115,103 @@ -- | Apply a function to all values stored in a trie trieMap :: (a -> b) -> Trie k a -> Trie k b - -- | Fold all the values store in a trie- trieFold :: (a -> b -> b) -> Trie k a -> b -> b- -- | Traverse the values stored in a trie trieTraverse :: Applicative f => (a -> f b) -> Trie k a -> f (Trie k b) -- | Show the representation of a trie trieShowsPrec :: Show a => Int -> Trie k a -> ShowS + -- | Apply a function to the values of a 'Trie' and keep the elements+ -- of the trie that result in a 'Just' value.+ mapMaybeWithKey :: (k -> a -> Maybe b) -> Trie k a -> Trie k b + -- | Fold a trie with a function of both key and value.+ foldWithKey :: (k -> a -> r -> r) -> r -> Trie k a -> r++ -- | Traverse a trie with a function of both key and value.+ traverseWithKey :: Applicative f => (k -> a -> f b) -> Trie k a -> f (Trie k b)++ mergeWithKey :: (k -> a -> b -> Maybe c) ->+ (Trie k a -> Trie k c) ->+ (Trie k b -> Trie k c) ->+ Trie k a -> Trie k b -> Trie k c++ -- Defaults using 'Generic' - type instance TrieRep k a = TrieRepDefault k a+ type instance TrieRep k = TrieRepDefault k - default empty ::- ( TrieRep k a ~ TrieRepDefault k a- ) =>- Trie k a- empty = MkTrie Nothing+ default empty :: ( TrieRep k ~ TrieRepDefault k) => Trie k a+ empty = genericEmpty default singleton ::- ( GTrieKey (Rep k), Generic k- , TrieRep k a ~ TrieRepDefault k a- ) =>+ ( GTrieKey (Rep k), Generic k , TrieRep k ~ TrieRepDefault k) => k -> a -> Trie k a- singleton k v = MkTrie $ Just $! gtrieSingleton (from k) v+ singleton = genericSingleton default trieNull ::- ( TrieRep k a ~ TrieRepDefault k a- ) =>+ ( TrieRep k ~ TrieRepDefault k) => Trie k a -> Bool- trieNull (MkTrie mb) = isNothing mb+ trieNull = genericTrieNull default lookup ::- ( GTrieKey (Rep k), Generic k- , TrieRep k a ~ TrieRepDefault k a- ) =>+ ( GTrieKey (Rep k), Generic k , TrieRep k ~ TrieRepDefault k) => k -> Trie k a -> Maybe a- lookup k (MkTrie t) = gtrieLookup (from k) =<< t+ lookup = genericLookup default insert ::- ( GTrieKey (Rep k), Generic k- , TrieRep k a ~ TrieRepDefault k a- ) =>+ ( GTrieKey (Rep k), Generic k , TrieRep k ~ TrieRepDefault k) => k -> a -> Trie k a -> Trie k a- insert k v (MkTrie Nothing) = MkTrie (Just $! gtrieSingleton (from k) v)- insert k v (MkTrie (Just t)) = MkTrie (Just $! gtrieInsert (from k) v t)+ insert = genericInsert default delete ::- ( GTrieKey (Rep k), Generic k- , TrieRep k a ~ TrieRepDefault k a- ) =>+ ( GTrieKey (Rep k), Generic k , TrieRep k ~ TrieRepDefault k) => k -> Trie k a -> Trie k a- delete _ t@(MkTrie Nothing) = t- delete k (MkTrie (Just t)) = MkTrie (gtrieDelete (from k) t)+ delete = genericDelete default trieMap ::- ( GTrieKey (Rep k)- , TrieRep k a ~ TrieRepDefault k a- , TrieRep k b ~ TrieRepDefault k b- ) =>+ ( GTrieKey (Rep k) , TrieRep k ~ TrieRepDefault k) => (a -> b) -> Trie k a -> Trie k b- trieMap f (MkTrie x) = MkTrie (fmap (gtrieMap f) $! x)-- default trieFold ::- ( GTrieKey (Rep k)- , TrieRep k a ~ TrieRepDefault k a- ) =>- (a -> b -> b) -> Trie k a -> b -> b- trieFold f (MkTrie (Just x)) z = gtrieFold f x z- trieFold _ (MkTrie Nothing) z = z+ trieMap = genericTrieMap default trieTraverse ::- ( GTrieKey (Rep k)- , TrieRep k a ~ TrieRepDefault k a- , TrieRep k b ~ TrieRepDefault k b- , Applicative f- ) =>+ ( GTrieKey (Rep k) , TrieRep k ~ TrieRepDefault k , Applicative f) => (a -> f b) -> Trie k a -> f (Trie k b)- trieTraverse f (MkTrie x) = fmap MkTrie (traverse (gtrieTraverse f) x)+ trieTraverse = genericTrieTraverse default trieShowsPrec ::- ( Show a, GTrieKeyShow (Rep k)- , TrieRep k a ~ TrieRepDefault k a- ) =>+ ( Show a, GTrieKeyShow (Rep k) , TrieRep k ~ TrieRepDefault k) => Int -> Trie k a -> ShowS- trieShowsPrec p (MkTrie (Just x)) = showsPrec p x- trieShowsPrec _ (MkTrie Nothing ) = showString "()"+ trieShowsPrec = genericTrieShowsPrec + default mapMaybeWithKey ::+ ( GTrieKey (Rep k) , Generic k, TrieRep k ~ TrieRepDefault k) =>+ (k -> a -> Maybe b) -> Trie k a -> Trie k b+ mapMaybeWithKey = genericMapMaybeWithKey++ default foldWithKey ::+ ( GTrieKey (Rep k) , TrieRep k ~ TrieRepDefault k, Generic k) =>+ (k -> a -> r -> r) -> r -> Trie k a -> r+ foldWithKey = genericFoldWithKey++ default traverseWithKey ::+ ( GTrieKey (Rep k) , TrieRep k ~ TrieRepDefault k, Generic k, Applicative f) =>+ (k -> a -> f b) -> Trie k a -> f (Trie k b)+ traverseWithKey = genericTraverseWithKey++ default mergeWithKey ::+ ( GTrieKey (Rep k) , TrieRep k ~ TrieRepDefault k, Generic k ) =>+ (k -> a -> b -> Maybe c) ->+ (Trie k a -> Trie k c) ->+ (Trie k b -> Trie k c) ->+ Trie k a -> Trie k b -> Trie k c+ mergeWithKey = genericMergeWithKey+ -- | The default implementation of a 'TrieRep' is 'GTrie' wrapped in -- a 'Maybe'. This wrapping is due to the 'GTrie' being a non-empty -- trie allowing all the of the "emptiness" to be represented at the -- top level for any given generically implemented key.-type TrieRepDefault k a = Maybe (GTrie (Rep k) a)+type TrieRepDefault k = Compose Maybe (GTrie (Rep k)) -- | Effectively an associated datatype of tries indexable by keys of type @k@. -- By using a separate newtype wrapper around the associated type synonym we're@@ -195,7 +226,7 @@ -- | 'Int' tries are implemented with 'IntMap'. instance TrieKey Int where- type TrieRep Int a = IntMap a+ type TrieRep Int = IntMap lookup k (MkTrie x) = IntMap.lookup k x insert k v (MkTrie t) = MkTrie (IntMap.insert k v t) delete k (MkTrie t) = MkTrie (IntMap.delete k t)@@ -203,21 +234,25 @@ singleton k v = MkTrie (IntMap.singleton k v) trieNull (MkTrie x) = IntMap.null x trieMap f (MkTrie x) = MkTrie (IntMap.map f x)- trieFold f (MkTrie x) z = IntMap.foldr f z x trieTraverse f (MkTrie x) = fmap MkTrie (traverse f x) trieShowsPrec p (MkTrie x) = showsPrec p x+ mapMaybeWithKey f (MkTrie x) = MkTrie (IntMap.mapMaybeWithKey f x)+ foldWithKey f z (MkTrie x) = IntMap.foldWithKey f z x+ traverseWithKey f (MkTrie x) = fmap MkTrie (IntMap.traverseWithKey f x)+ mergeWithKey f g h (MkTrie x) (MkTrie y) = MkTrie (IntMap.mergeWithKey f (coerce g) (coerce h) x y) {-# INLINE empty #-} {-# INLINE insert #-} {-# INLINE lookup #-} {-# INLINE delete #-}+ {-# INLINE foldWithKey #-} {-# INLINE trieTraverse #-} {-# INLINE trieNull #-} {-# INLINE trieMap #-}- {-# INLINE trieFold #-}+ {-# INLINE mergeWithKey #-} -- | 'Integer' tries are implemented with 'Map'. instance TrieKey Integer where- type TrieRep Integer a = Map Integer a+ type TrieRep Integer = Map Integer lookup k (MkTrie t) = Map.lookup k t insert k v (MkTrie t) = MkTrie (Map.insert k v t) delete k (MkTrie t) = MkTrie (Map.delete k t)@@ -225,21 +260,25 @@ singleton k v = MkTrie (Map.singleton k v) trieNull (MkTrie x) = Map.null x trieMap f (MkTrie x) = MkTrie (Map.map f x)- trieFold f (MkTrie x) z = Map.foldr f z x trieTraverse f (MkTrie x) = fmap MkTrie (traverse f x) trieShowsPrec p (MkTrie x) = showsPrec p x+ mapMaybeWithKey f (MkTrie x) = MkTrie (Map.mapMaybeWithKey f x)+ foldWithKey f z (MkTrie x) = Map.foldrWithKey f z x+ traverseWithKey f (MkTrie x) = fmap MkTrie (Map.traverseWithKey f x)+ mergeWithKey f g h (MkTrie x) (MkTrie y) = MkTrie (Map.mergeWithKey f (coerce g) (coerce h) x y) {-# INLINE empty #-} {-# INLINE insert #-} {-# INLINE lookup #-} {-# INLINE delete #-} {-# INLINE trieNull #-} {-# INLINE trieMap #-}- {-# INLINE trieFold #-}+ {-# INLINE foldWithKey #-}+ {-# INLINE mergeWithKey #-} {-# INLINE trieTraverse #-} -- | 'Char tries are implemented with 'IntMap'. instance TrieKey Char where- type TrieRep Char a = IntMap a+ type TrieRep Char = IntMap lookup k (MkTrie t) = IntMap.lookup (ord k) t delete k (MkTrie t) = MkTrie (IntMap.delete (ord k) t) insert k v (MkTrie t) = MkTrie (IntMap.insert (ord k) v t)@@ -247,9 +286,12 @@ singleton k v = MkTrie (IntMap.singleton (ord k) v) trieNull (MkTrie x) = IntMap.null x trieMap f (MkTrie x) = MkTrie (IntMap.map f x)- trieFold f (MkTrie x) z = IntMap.foldr f z x trieTraverse f (MkTrie x) = fmap MkTrie (traverse f x) trieShowsPrec p (MkTrie x) = showsPrec p x+ mapMaybeWithKey f (MkTrie x) = MkTrie (IntMap.mapMaybeWithKey (f . chr) x)+ foldWithKey f z (MkTrie x) = IntMap.foldrWithKey (f . chr) z x+ traverseWithKey f (MkTrie x) = fmap MkTrie (IntMap.traverseWithKey (f . chr) x)+ mergeWithKey f g h (MkTrie x) (MkTrie y) = MkTrie (IntMap.mergeWithKey (f . chr) (coerce g) (coerce h) x y) {-# INLINE empty #-} {-# INLINE insert #-} {-# INLINE lookup #-}@@ -257,9 +299,10 @@ {-# INLINE trieNull #-} {-# INLINE trieTraverse #-} {-# INLINE trieMap #-}- {-# INLINE trieFold #-}+ {-# INLINE foldWithKey #-}+ {-# INLINE mergeWithKey #-} -newtype OrdKey k = OrdKey k+newtype OrdKey k = OrdKey { getOrdKey :: k } deriving (Read, Show, Eq, Ord) -- | 'OrdKey' tries are implemented with 'Map', this is@@ -267,7 +310,7 @@ -- to force the use of a 'Map' than to use the generically -- derived structure. instance (Show k, Ord k) => TrieKey (OrdKey k) where- type TrieRep (OrdKey k) a = Map k a+ type TrieRep (OrdKey k) = Map k lookup (OrdKey k) (MkTrie x) = Map.lookup k x insert (OrdKey k) v (MkTrie x) = MkTrie (Map.insert k v x) delete (OrdKey k) (MkTrie x) = MkTrie (Map.delete k x)@@ -275,17 +318,21 @@ singleton (OrdKey k) v = MkTrie (Map.singleton k v) trieNull (MkTrie x) = Map.null x trieMap f (MkTrie x) = MkTrie (Map.map f x)- trieFold f (MkTrie x) z = Map.foldr f z x trieTraverse f (MkTrie x) = fmap MkTrie (traverse f x) trieShowsPrec p (MkTrie x) = showsPrec p x+ mapMaybeWithKey f (MkTrie x) = MkTrie (Map.mapMaybeWithKey (f . OrdKey) x)+ foldWithKey f z (MkTrie x) = Map.foldrWithKey (f . OrdKey) z x+ traverseWithKey f (MkTrie x) = fmap MkTrie (Map.traverseWithKey (f . OrdKey) x)+ mergeWithKey f g h (MkTrie x) (MkTrie y) = MkTrie (Map.mergeWithKey (f . OrdKey) (coerce g) (coerce h) x y) {-# INLINE empty #-} {-# INLINE insert #-} {-# INLINE lookup #-} {-# INLINE delete #-}+ {-# INLINE foldWithKey #-} {-# INLINE trieNull #-} {-# INLINE trieMap #-}- {-# INLINE trieFold #-} {-# INLINE trieTraverse #-}+ {-# INLINE mergeWithKey #-} {-# INLINE trieShowsPrec #-} ------------------------------------------------------------------------------@@ -301,19 +348,164 @@ instance TrieKey k => TrieKey [k] ------------------------------------------------------------------------------+-- Generic 'TrieKey' method implementations+------------------------------------------------------------------------------++-- | Generic implementation of 'lookup'. This is the default implementation.+genericLookup ::+ ( GTrieKey (Rep k), Generic k+ , TrieRep k ~ TrieRepDefault k+ ) =>+ k -> Trie k a -> Maybe a+genericLookup k (MkTrie (Compose t)) = gtrieLookup (from k) =<< t+{-# INLINABLE genericLookup #-}++-- | Generic implementation of 'trieNull'. This is the default implementation.+genericTrieNull ::+ ( TrieRep k ~ TrieRepDefault k+ ) =>+ Trie k a -> Bool+genericTrieNull (MkTrie (Compose mb)) = isNothing mb+{-# INLINABLE genericTrieNull #-}++-- | Generic implementation of 'singleton'. This is the default implementation.+genericSingleton ::+ ( GTrieKey (Rep k), Generic k+ , TrieRep k ~ TrieRepDefault k+ ) =>+ k -> a -> Trie k a+genericSingleton k v = MkTrie $ Compose $ Just $! gtrieSingleton (from k) v+{-# INLINABLE genericSingleton #-}++-- | Generic implementation of 'empty'. This is the default implementation.+genericEmpty ::+ ( TrieRep k ~ TrieRepDefault k+ ) =>+ Trie k a+genericEmpty = MkTrie (Compose Nothing)+{-# INLINABLE genericEmpty #-}++-- | Generic implementation of 'insert'. This is the default implementation.+genericInsert ::+ ( GTrieKey (Rep k), Generic k+ , TrieRep k ~ TrieRepDefault k+ ) =>+ k -> a -> Trie k a -> Trie k a+genericInsert k v (MkTrie (Compose m)) =+ case m of+ Nothing -> MkTrie (Compose (Just $! gtrieSingleton (from k) v))+ Just t -> MkTrie (Compose (Just $! gtrieInsert (from k) v t))+{-# INLINABLE genericInsert #-}++-- | Generic implementation of 'delete'. This is the default implementation.+genericDelete ::+ ( GTrieKey (Rep k), Generic k+ , TrieRep k ~ TrieRepDefault k+ ) =>+ k -> Trie k a -> Trie k a+genericDelete k (MkTrie (Compose m)) = MkTrie (Compose (gtrieDelete (from k) =<< m))+{-# INLINABLE genericDelete #-}++-- | Generic implementation of 'trieMap'. This is the default implementation.+genericTrieMap ::+ ( GTrieKey (Rep k)+ , TrieRep k ~ TrieRepDefault k+ ) =>+ (a -> b) -> Trie k a -> Trie k b+genericTrieMap f (MkTrie (Compose x)) = MkTrie (Compose (fmap (gtrieMap f) $! x))+{-# INLINABLE genericTrieMap #-}+++-- | Generic implementation of 'trieTraverse'. This is the default implementation.+genericTrieTraverse ::+ ( GTrieKey (Rep k)+ , TrieRep k ~ TrieRepDefault k+ , Applicative f+ ) =>+ (a -> f b) -> Trie k a -> f (Trie k b)+genericTrieTraverse f (MkTrie (Compose x)) =+ fmap (MkTrie . Compose) (traverse (gtrieTraverse f) x)+{-# INLINABLE genericTrieTraverse #-}++-- | Generic implementation of 'trieShowsPrec'. This is the default implementation.+genericTrieShowsPrec ::+ ( Show a, GTrieKeyShow (Rep k)+ , TrieRep k ~ TrieRepDefault k+ ) =>+ Int -> Trie k a -> ShowS+genericTrieShowsPrec p (MkTrie (Compose m)) =+ case m of+ Just x -> showsPrec p x+ Nothing -> showString "()"+{-# INLINABLE genericTrieShowsPrec #-}++-- | Generic implementation of 'mapMaybe'. This is the default implementation.+genericMapMaybeWithKey ::+ ( GTrieKey (Rep k), Generic k+ , TrieRep k ~ TrieRepDefault k+ ) =>+ (k -> a -> Maybe b) -> Trie k a -> Trie k b+genericMapMaybeWithKey f (MkTrie (Compose x)) = MkTrie (Compose (gmapMaybeWithKey (f . to) =<< x))+{-# INLINABLE genericMapMaybeWithKey #-}++-- | Generic implementation of 'foldWithKey'. This is the default implementation.+genericFoldWithKey ::+ ( GTrieKey (Rep k), Generic k+ , TrieRep k ~ TrieRepDefault k+ ) =>+ (k -> a -> r -> r) -> r -> Trie k a -> r+genericFoldWithKey f z (MkTrie (Compose m)) =+ case m of+ Nothing -> z+ Just x -> gfoldWithKey (f . to) z x+{-# INLINABLE genericFoldWithKey #-}++-- | Generic implementation of 'traverseWithKey'. This is the default implementation.+genericTraverseWithKey ::+ ( GTrieKey (Rep k), Generic k+ , TrieRep k ~ TrieRepDefault k+ , Applicative f+ ) =>+ (k -> a -> f b) -> Trie k a -> f (Trie k b)+genericTraverseWithKey f (MkTrie (Compose m)) = fmap (MkTrie . Compose) (traverse (gtraverseWithKey (f . to)) m)+{-# INLINABLE genericTraverseWithKey #-}++-- | Generic implementation of 'mergeWithKey'. This is the default implementation.+genericMergeWithKey ::+ ( GTrieKey (Rep k), Generic k+ , TrieRep k ~ TrieRepDefault k+ ) =>+ (k -> a -> b -> Maybe c) -> (Trie k a -> Trie k c) -> (Trie k b -> Trie k c) ->+ Trie k a -> Trie k b -> Trie k c+genericMergeWithKey f g h (MkTrie (Compose x)) (MkTrie (Compose y)) =+ case (x,y) of+ (Nothing, Nothing) -> MkTrie (Compose Nothing)+ (Just{} , Nothing) -> g (MkTrie (Compose x))+ (Nothing, Just{} ) -> h (MkTrie (Compose y))+ (Just x', Just y') -> MkTrie (Compose (gmergeWithKey (f . to) (aux g) (aux h) x' y'))+ where+ aux k t = case k (MkTrie (Compose (Just t))) of+ MkTrie (Compose r) -> r+{-# INLINABLE genericMergeWithKey #-}+++------------------------------------------------------------------------------ -- Generic implementation class ------------------------------------------------------------------------------ -- | Mapping of generic representation of keys to trie structures. data family GTrie (f :: * -> *) a-newtype instance GTrie (M1 i c f) a = MTrie { unMTrie :: GTrie f a }+newtype instance GTrie (M1 i c f) a = MTrie (GTrie f a) data instance GTrie (f :+: g) a = STrieL !(GTrie f a) | STrieR !(GTrie g a) | STrieB !(GTrie f a) !(GTrie g a) newtype instance GTrie (f :*: g) a = PTrie (GTrie f (GTrie g a)) newtype instance GTrie (K1 i k) a = KTrie (Trie k a) newtype instance GTrie U1 a = UTrie a-data instance GTrie V1 a = VTrie+data instance GTrie V1 a +instance GTrieKey f => Functor (GTrie f) where+ fmap = gtrieMap+ -- | TrieKey operations on Generic representations used to provide -- the default implementations of tries. class GTrieKey f where@@ -322,8 +514,14 @@ gtrieSingleton :: f p -> a -> GTrie f a gtrieDelete :: f p -> GTrie f a -> Maybe (GTrie f a) gtrieMap :: (a -> b) -> GTrie f a -> GTrie f b- gtrieFold :: (a -> b -> b) -> GTrie f a -> b -> b gtrieTraverse :: Applicative m => (a -> m b) -> GTrie f a -> m (GTrie f b)+ gmapMaybeWithKey :: (f p -> a -> Maybe b) -> GTrie f a -> Maybe (GTrie f b)+ gfoldWithKey :: (f p -> a -> r -> r) -> r -> GTrie f a -> r+ gtraverseWithKey :: Applicative m => (f p -> a -> m b) -> GTrie f a -> m (GTrie f b)+ gmergeWithKey :: (f p -> a -> b -> Maybe c) ->+ (GTrie f a -> Maybe (GTrie f c)) ->+ (GTrie f b -> Maybe (GTrie f c)) ->+ GTrie f a -> GTrie f b -> Maybe (GTrie f c) -- | The 'GTrieKeyShow' class provides generic implementations -- of 'showsPrec'. This class is separate due to its implementation@@ -342,15 +540,20 @@ gtrieSingleton (M1 k) v = MTrie (gtrieSingleton k v) gtrieDelete (M1 k) (MTrie x) = fmap MTrie (gtrieDelete k x) gtrieMap f (MTrie x) = MTrie (gtrieMap f x)- gtrieFold f (MTrie x) = gtrieFold f x gtrieTraverse f (MTrie x) = fmap MTrie (gtrieTraverse f x)+ gmapMaybeWithKey f (MTrie x) = fmap MTrie (gmapMaybeWithKey (f . M1) x)+ gfoldWithKey f z (MTrie x) = gfoldWithKey (f . M1) z x+ gtraverseWithKey f (MTrie x) = fmap MTrie (gtraverseWithKey (f . M1) x)+ gmergeWithKey f g h (MTrie x) (MTrie y) = fmap MTrie (gmergeWithKey (f . M1) (coerce g) (coerce h) x y) {-# INLINE gtrieLookup #-} {-# INLINE gtrieInsert #-} {-# INLINE gtrieSingleton #-} {-# INLINE gtrieDelete #-} {-# INLINE gtrieMap #-}- {-# INLINE gtrieFold #-}+ {-# INLINE gmapMaybeWithKey #-} {-# INLINE gtrieTraverse #-}+ {-# INLINE gfoldWithKey #-}+ {-# INLINE gtraverseWithKey #-} data MProxy c (f :: * -> *) a = MProxy @@ -369,24 +572,40 @@ -- Generic implementation for fields ------------------------------------------------------------------------------ +checkNull :: TrieKey k => Trie k a -> Maybe (Trie k a)+checkNull x+ | trieNull x = Nothing+ | otherwise = Just x+ -- | Generic fields are represented by tries of the field type. instance TrieKey k => GTrieKey (K1 i k) where gtrieLookup (K1 k) (KTrie x) = lookup k x gtrieInsert (K1 k) v (KTrie t) = KTrie (insert k v t) gtrieSingleton (K1 k) v = KTrie (singleton k v)- gtrieDelete (K1 k) (KTrie t) = let m = delete k t- in if trieNull m then Nothing- else Just (KTrie m)+ gtrieDelete (K1 k) (KTrie t) = fmap KTrie (checkNull (delete k t)) gtrieMap f (KTrie x) = KTrie (trieMap f x)- gtrieFold f (KTrie x ) = trieFold f x gtrieTraverse f (KTrie x) = fmap KTrie (traverse f x)+ gmapMaybeWithKey f (KTrie x) = fmap KTrie (checkNull (mapMaybeWithKey (f . K1) x))+ gfoldWithKey f z (KTrie x) = foldWithKey (f . K1) z x+ gtraverseWithKey f (KTrie x) = fmap KTrie (traverseWithKey (f . K1) x)+ gmergeWithKey f g h (KTrie x) (KTrie y) = fmap KTrie (checkNull (mergeWithKey (f . K1) g' h' x y))+ where+ g' t = case g (KTrie t) of+ Just (KTrie t') -> t'+ Nothing -> empty+ h' t = case h (KTrie t) of+ Just (KTrie t') -> t'+ Nothing -> empty {-# INLINE gtrieLookup #-} {-# INLINE gtrieInsert #-} {-# INLINE gtrieSingleton #-} {-# INLINE gtrieDelete #-} {-# INLINE gtrieMap #-}- {-# INLINE gtrieFold #-} {-# INLINE gtrieTraverse #-}+ {-# INLINE gfoldWithKey #-}+ {-# INLINE gtraverseWithKey #-}+ {-# INLINE gmergeWithKey #-}+ {-# INLINE gmapMaybeWithKey #-} instance TrieKey k => GTrieKeyShow (K1 i k) where gtrieShowsPrec p (KTrie x) = showsPrec p x@@ -409,15 +628,39 @@ Just tj -> Just (PTrie (gtrieInsert i tj t)) gtrieSingleton (i :*: j) v = PTrie (gtrieSingleton i (gtrieSingleton j v)) gtrieMap f (PTrie x) = PTrie (gtrieMap (gtrieMap f) x)- gtrieFold f (PTrie x) = gtrieFold (gtrieFold f) x gtrieTraverse f (PTrie x) = fmap PTrie (gtrieTraverse (gtrieTraverse f) x)+ gmapMaybeWithKey f (PTrie x) = fmap PTrie (gmapMaybeWithKey (\i -> gmapMaybeWithKey (\j -> f (i:*:j))) x)+ gfoldWithKey f z (PTrie x) = gfoldWithKey (\i m r -> gfoldWithKey (\j -> f (i:*:j)) r m) z x+ gtraverseWithKey f (PTrie x) = fmap PTrie (gtraverseWithKey (\i ->+ gtraverseWithKey (\j -> f (i :*: j))) x)+ gmergeWithKey f g h (PTrie x) (PTrie y) =+ fmap+ PTrie+ (gmergeWithKey+ (\i ->+ gmergeWithKey+ (\j -> f (i:*:j))+ (g' i)+ (h' i))+ (coerce g)+ (coerce h)+ x+ y)+ where+ g' i t = do PTrie t' <- g (PTrie (gtrieSingleton i t))+ gtrieLookup i t'+ h' i t = do PTrie t' <- h (PTrie (gtrieSingleton i t))+ gtrieLookup i t' {-# INLINE gtrieLookup #-} {-# INLINE gtrieInsert #-} {-# INLINE gtrieDelete #-} {-# INLINE gtrieSingleton #-} {-# INLINE gtrieMap #-}- {-# INLINE gtrieFold #-} {-# INLINE gtrieTraverse #-}+ {-# INLINE gfoldWithKey #-}+ {-# INLINE gtraverseWithKey #-}+ {-# INLINE gmergeWithKey #-}+ {-# INLINE gmapMaybeWithKey #-} instance (GTrieKeyShow f, GTrieKeyShow g) => GTrieKeyShow (f :*: g) where gtrieShowsPrec p (PTrie x) = showsPrec p x@@ -461,21 +704,69 @@ gtrieMap f (STrieL x) = STrieL (gtrieMap f x) gtrieMap f (STrieR y) = STrieR (gtrieMap f y) - gtrieFold f (STrieB x y) = gtrieFold f x . gtrieFold f y- gtrieFold f (STrieL x) = gtrieFold f x- gtrieFold f (STrieR y) = gtrieFold f y- gtrieTraverse f (STrieB x y) = liftA2 STrieB (gtrieTraverse f x) (gtrieTraverse f y) gtrieTraverse f (STrieL x) = fmap STrieL (gtrieTraverse f x) gtrieTraverse f (STrieR y) = fmap STrieR (gtrieTraverse f y) + gmapMaybeWithKey f (STrieL x) = fmap STrieL (gmapMaybeWithKey (f . L1) x)+ gmapMaybeWithKey f (STrieR y) = fmap STrieR (gmapMaybeWithKey (f . R1) y)+ gmapMaybeWithKey f (STrieB x y) = case (gmapMaybeWithKey (f . L1) x, gmapMaybeWithKey (f . R1) y) of+ (Nothing, Nothing) -> Nothing+ (Just x', Nothing) -> Just (STrieL x')+ (Nothing, Just y') -> Just (STrieR y')+ (Just x', Just y') -> Just (STrieB x' y')++ gfoldWithKey f z (STrieL x) = gfoldWithKey (f . L1) z x+ gfoldWithKey f z (STrieR y) = gfoldWithKey (f . R1) z y+ gfoldWithKey f z (STrieB x y) = gfoldWithKey (f . L1) (gfoldWithKey (f . R1) z y) x++ gtraverseWithKey f (STrieL x) = fmap STrieL (gtraverseWithKey (f . L1) x)+ gtraverseWithKey f (STrieR y) = fmap STrieR (gtraverseWithKey (f . R1) y)+ gtraverseWithKey f (STrieB x y) = liftA2 STrieB (gtraverseWithKey (f . L1) x)+ (gtraverseWithKey (f . R1) y)++ gmergeWithKey f g h x0 y0 =+ case (split x0, split y0) of+ ((xl,xr),(yl,yr)) -> build (mergel xl yl) (merger xr yr)+ where+ split (STrieL x) = (Just x, Nothing)+ split (STrieR y) = (Nothing, Just y)+ split (STrieB x y) = (Just x, Just y)++ build (Just x) (Just y) = Just (STrieB x y)+ build (Just x) Nothing = Just (STrieL x)+ build Nothing (Just y) = Just (STrieR y)+ build Nothing Nothing = Nothing++ mergel Nothing Nothing = Nothing+ mergel (Just x) Nothing = gl x+ mergel Nothing (Just y) = hl y+ mergel (Just x) (Just y) = gmergeWithKey (f . L1) gl hl x y++ merger Nothing Nothing = Nothing+ merger (Just x) Nothing = gr x+ merger Nothing (Just y) = hr y+ merger (Just x) (Just y) = gmergeWithKey (f . R1) gr hr x y++ gl t = do STrieL t' <- g (STrieL t)+ return t'+ gr t = do STrieR t' <- g (STrieR t)+ return t'+ hl t = do STrieL t' <- h (STrieL t)+ return t'+ hr t = do STrieR t' <- h (STrieR t)+ return t'+ {-# INLINE gtrieLookup #-} {-# INLINE gtrieInsert #-} {-# INLINE gtrieDelete #-} {-# INLINE gtrieSingleton #-}- {-# INLINE gtrieFold #-} {-# INLINE gtrieTraverse #-} {-# INLINE gtrieMap #-}+ {-# INLINE gfoldWithKey #-}+ {-# INLINE gtraverseWithKey #-}+ {-# INLINE gmergeWithKey #-}+ {-# INLINE gmapMaybeWithKey #-} instance (GTrieKeyShow f, GTrieKeyShow g) => GTrieKeyShow (f :+: g) where gtrieShowsPrec p (STrieB x y) = showParen (p > 10)@@ -501,15 +792,21 @@ gtrieDelete _ _ = Nothing gtrieSingleton _ = UTrie gtrieMap f (UTrie x) = UTrie (f x)- gtrieFold f (UTrie x) = f x gtrieTraverse f (UTrie x) = fmap UTrie (f x)+ gmapMaybeWithKey f (UTrie x) = fmap UTrie (f U1 x)+ gfoldWithKey f z (UTrie x) = f U1 x z+ gtraverseWithKey f (UTrie x) = fmap UTrie (f U1 x)+ gmergeWithKey f _ _ (UTrie x) (UTrie y) = fmap UTrie (f U1 x y) {-# INLINE gtrieLookup #-} {-# INLINE gtrieInsert #-} {-# INLINE gtrieDelete #-} {-# INLINE gtrieSingleton #-}- {-# INLINE gtrieFold #-} {-# INLINE gtrieTraverse #-} {-# INLINE gtrieMap #-}+ {-# INLINE gfoldWithKey #-}+ {-# INLINE gtraverseWithKey #-}+ {-# INLINE gmergeWithKey #-}+ {-# INLINE gmapMaybeWithKey #-} instance GTrieKeyShow U1 where gtrieShowsPrec p (UTrie x) = showsPrec p x@@ -520,20 +817,26 @@ -- | Tries of types without constructors are represented by a unit. instance GTrieKey V1 where- gtrieLookup k _ = k `seq` error "GTrieKey.V1: gtrieLookup"- gtrieInsert k _ _ = k `seq` error "GTrieKey.V1: gtrieInsert"- gtrieDelete k _ = k `seq` error "GTrieKey.V1: gtrieDelete"+ gtrieLookup k t = k `seq` t `seq` error "GTrieKey.V1: gtrieLookup"+ gtrieInsert k _ t = k `seq` t `seq` error "GTrieKey.V1: gtrieInsert"+ gtrieDelete k t = k `seq` t `seq` error "GTrieKey.V1: gtrieDelete" gtrieSingleton k _ = k `seq` error "GTrieKey.V1: gtrieSingleton"- gtrieMap _ _ = VTrie- gtrieFold _ _ = id- gtrieTraverse _ _ = pure VTrie+ gtrieMap _ t = t `seq` error "GTrieKey.V1: gtrieMap"+ gtrieTraverse _ t = t `seq` error "GTrieKey.V1: gtrieTraverse"+ gmapMaybeWithKey _ t = t `seq` error "GTrieKey.V1: gmapMaybeWithKey"+ gfoldWithKey _ _ t = t `seq` error "GTrieKey.V1: gmapFoldWithKey"+ gtraverseWithKey _ t = t `seq` error "GTrieKey.V1: gtraverseWithKey"+ gmergeWithKey _ _ _ t u = t `seq` u `seq` error "GTrieKey.V1: gmergeWithKey" {-# INLINE gtrieLookup #-} {-# INLINE gtrieInsert #-} {-# INLINE gtrieDelete #-} {-# INLINE gtrieSingleton #-}- {-# INLINE gtrieFold #-} {-# INLINE gtrieMap #-} {-# INLINE gtrieTraverse #-}+ {-# INLINE gfoldWithKey #-}+ {-# INLINE gtraverseWithKey #-}+ {-# INLINE gmergeWithKey #-}+ {-# INLINE gmapMaybeWithKey #-} instance GTrieKeyShow V1 where gtrieShowsPrec _ _ = showString "()"@@ -545,7 +848,6 @@ -- | Construct a trie from a list of key/value pairs fromList :: TrieKey k => [(k,v)] -> Trie k v fromList = foldl' (\acc (k,v) -> insert k v acc) empty-{-# INLINE fromList #-} -- | Alter the values of a trie. The function will take the value stored -- as the given key if one exists and should return a value to insert at@@ -564,6 +866,40 @@ notMember :: TrieKey k => k -> Trie k a -> Bool notMember k t = isNothing (lookup k t) +-- | Transform 'Trie' to an association list.+toList :: TrieKey k => Trie k a -> [(k,a)]+toList = foldWithKey (\k v xs -> (k,v) : xs) []++union :: TrieKey k => Trie k a -> Trie k a -> Trie k a+union = mergeWithKey (\_ a _ -> Just a) id id++unionWith :: TrieKey k => (a -> a -> a) -> Trie k a -> Trie k a -> Trie k a+unionWith f = mergeWithKey (\_ a b -> Just (f a b)) id id++unionWithKey :: TrieKey k => (k -> a -> a -> a) -> Trie k a -> Trie k a -> Trie k a+unionWithKey f = mergeWithKey (\k a b -> Just (f k a b)) id id++intersection :: TrieKey k => Trie k a -> Trie k b -> Trie k a+intersection = mergeWithKey (\_ a _ -> Just a) (const empty) (const empty)++intersectionWith :: TrieKey k => (a -> b -> c) -> Trie k a -> Trie k b -> Trie k c+intersectionWith f = mergeWithKey (\_ a b -> Just (f a b)) (const empty) (const empty)++intersectionWithKey :: TrieKey k => (k -> a -> b -> c) -> Trie k a -> Trie k b -> Trie k c+intersectionWithKey f = mergeWithKey (\k a b -> Just (f k a b)) (const empty) (const empty)++difference :: TrieKey k => Trie k a -> Trie k b -> Trie k a+difference = mergeWithKey (\_ _ _ -> Nothing) id (const empty)++differenceWith :: TrieKey k => (a -> b -> Maybe a) -> Trie k a -> Trie k b -> Trie k a+differenceWith f = mergeWithKey (\_ -> f) id (const empty)++differenceWithKey :: TrieKey k => (k -> a -> b -> Maybe a) -> Trie k a -> Trie k b -> Trie k a+differenceWithKey f = mergeWithKey f id (const empty)++mapMaybe :: TrieKey k => (a -> Maybe b) -> Trie k a -> Trie k b+mapMaybe f = mapMaybeWithKey (\_ -> f)+ ------------------------------------------------------------------------------ -- Various instances for Trie ------------------------------------------------------------------------------@@ -578,7 +914,7 @@ fmap = trieMap instance TrieKey k => Foldable (Trie k) where- foldr f z t = trieFold f t z+ foldr f = foldWithKey (\_ -> f) instance TrieKey k => Traversable (Trie k) where traverse = trieTraverse