packages feed

radix-tree 0.1 → 1.0.0.0

raw patch · 77 files changed

+32092/−889 lines, 77 filesdep +hspecdep +randomdep +template-haskelldep −HUnitdep −QuickCheckdep −gaugedep ~basedep ~bytestringdep ~containerssetup-changednew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: hspec, random, template-haskell

Dependencies removed: HUnit, QuickCheck, gauge, hashtables, tasty, tasty-hunit, tasty-quickcheck, unordered-containers

Dependency ranges changed: base, bytestring, containers, deepseq, primitive, text

API changes (from Hackage documentation)

- Data.RadixTree: data RadixTree a
- Data.RadixTree: elems :: RadixTree a -> [a]
- Data.RadixTree: empty :: RadixTree a
- Data.RadixTree: fromList :: [(ShortByteString, a)] -> RadixTree a
- Data.RadixTree: insert :: forall a. ShortByteString -> a -> RadixTree a -> RadixTree a
- Data.RadixTree: insertWith :: forall a. (a -> a -> a) -> ShortByteString -> a -> RadixTree a -> RadixTree a
- Data.RadixTree: keys :: RadixTree a -> [ShortByteString]
- Data.RadixTree: keysSet :: RadixTree a -> Set ShortByteString
- Data.RadixTree: lookup :: forall a. ShortByteString -> RadixTree a -> Maybe a
- Data.RadixTree: mapMaybe :: forall a b. (a -> Maybe b) -> RadixTree a -> RadixTree b
- Data.RadixTree: null :: RadixTree a -> Bool
- Data.RadixTree: size :: RadixTree a -> Int
- Data.RadixTree: toAscList :: forall a. RadixTree a -> [(ShortByteString, a)]
- Data.RadixTree: toList :: RadixTree a -> [(ShortByteString, a)]
- Data.RadixTree: union :: RadixTree a -> RadixTree a -> RadixTree a
- Data.RadixTree: unionWith :: forall a. (a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a
- Data.RadixTree.Internal: RadixNode :: !Maybe a -> !IntMap (RadixTree a) -> RadixTree a
- Data.RadixTree.Internal: RadixStr :: !Maybe a -> {-# UNPACK #-} !ShortByteString -> !RadixTree a -> RadixTree a
- Data.RadixTree.Internal: data RadixTree a
- Data.RadixTree.Internal: elems :: RadixTree a -> [a]
- Data.RadixTree.Internal: empty :: RadixTree a
- Data.RadixTree.Internal: fromList :: [(ShortByteString, a)] -> RadixTree a
- Data.RadixTree.Internal: insert :: forall a. ShortByteString -> a -> RadixTree a -> RadixTree a
- Data.RadixTree.Internal: insertWith :: forall a. (a -> a -> a) -> ShortByteString -> a -> RadixTree a -> RadixTree a
- Data.RadixTree.Internal: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Data.RadixTree.Internal.RadixTree a)
- Data.RadixTree.Internal: instance Data.Foldable.Foldable Data.RadixTree.Internal.RadixTree
- Data.RadixTree.Internal: instance Data.Traversable.Traversable Data.RadixTree.Internal.RadixTree
- Data.RadixTree.Internal: instance GHC.Base.Functor Data.RadixTree.Internal.RadixTree
- Data.RadixTree.Internal: instance GHC.Generics.Generic (Data.RadixTree.Internal.RadixTree a)
- Data.RadixTree.Internal: instance GHC.Generics.Generic Data.RadixTree.Internal.Mismatch
- Data.RadixTree.Internal: instance GHC.Show.Show Data.RadixTree.Internal.Mismatch
- Data.RadixTree.Internal: instance GHC.Show.Show a => GHC.Show.Show (Data.RadixTree.Internal.RadixTree a)
- Data.RadixTree.Internal: keys :: RadixTree a -> [ShortByteString]
- Data.RadixTree.Internal: keysSet :: RadixTree a -> Set ShortByteString
- Data.RadixTree.Internal: lookup :: forall a. ShortByteString -> RadixTree a -> Maybe a
- Data.RadixTree.Internal: mapMaybe :: forall a b. (a -> Maybe b) -> RadixTree a -> RadixTree b
- Data.RadixTree.Internal: null :: RadixTree a -> Bool
- Data.RadixTree.Internal: size :: RadixTree a -> Int
- Data.RadixTree.Internal: toAscList :: forall a. RadixTree a -> [(ShortByteString, a)]
- Data.RadixTree.Internal: toList :: RadixTree a -> [(ShortByteString, a)]
- Data.RadixTree.Internal: union :: RadixTree a -> RadixTree a -> RadixTree a
- Data.RadixTree.Internal: unionWith :: forall a. (a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a
+ Data.Patricia.Word.Lazy: Equal :: PartialOrdering
+ Data.Patricia.Word.Lazy: Incomparable :: PartialOrdering
+ Data.Patricia.Word.Lazy: Lookup :: {-# UNPACK #-} !Word -> a -> Lookup a
+ Data.Patricia.Word.Lazy: Subset :: PartialOrdering
+ Data.Patricia.Word.Lazy: Superset :: PartialOrdering
+ Data.Patricia.Word.Lazy: ViewL :: {-# UNPACK #-} !Lookup a -> !Patricia a -> ViewL a
+ Data.Patricia.Word.Lazy: ViewR :: !Patricia a -> {-# UNPACK #-} !Lookup a -> ViewR a
+ Data.Patricia.Word.Lazy: adjust :: (a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: adjustL :: (a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: adjustLWithKey :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: adjustMax :: (a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: adjustMaxWithKey :: (Word -> a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: adjustMin :: (a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: adjustMinWithKey :: (Word -> a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: adjustR :: (a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: adjustRWithKey :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: adjustRange :: (a -> a) -> Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: adjustRangeWithKey :: (Word -> a -> a) -> Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: alter :: (Maybe a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: compare :: (a -> b -> Bool) -> Patricia a -> Patricia b -> PartialOrdering
+ Data.Patricia.Word.Lazy: data Lookup a
+ Data.Patricia.Word.Lazy: data PartialOrdering
+ Data.Patricia.Word.Lazy: data Patricia a
+ Data.Patricia.Word.Lazy: data Range
+ Data.Patricia.Word.Lazy: data ViewL a
+ Data.Patricia.Word.Lazy: data ViewR a
+ Data.Patricia.Word.Lazy: delete :: Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: deleteL :: Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: deleteMax :: Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: deleteMin :: Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: deleteR :: Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: deleteRange :: Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: difference :: Patricia a -> Patricia b -> Patricia a
+ Data.Patricia.Word.Lazy: differenceWith :: (a -> b -> Maybe a) -> Patricia a -> Patricia b -> Patricia a
+ Data.Patricia.Word.Lazy: differenceWithKey :: (Word -> a -> b -> Maybe a) -> Patricia a -> Patricia b -> Patricia a
+ Data.Patricia.Word.Lazy: disjoint :: Patricia a -> Patricia b -> Bool
+ Data.Patricia.Word.Lazy: empty :: Patricia a
+ Data.Patricia.Word.Lazy: filter :: (a -> Bool) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: filterWithKey :: (Word -> a -> Bool) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: find :: a -> Word -> Patricia a -> a
+ Data.Patricia.Word.Lazy: foldMap :: Monoid m => (a -> m) -> Patricia a -> m
+ Data.Patricia.Word.Lazy: foldMapWithKey :: Monoid m => (Word -> a -> m) -> Patricia a -> m
+ Data.Patricia.Word.Lazy: foldl :: (b -> a -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Lazy: foldl' :: (b -> a -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Lazy: foldlWithKey :: (b -> Word -> a -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Lazy: foldlWithKey' :: (b -> Word -> a -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Lazy: foldr :: (a -> b -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Lazy: foldr' :: (a -> b -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Lazy: foldrWithKey :: (Word -> a -> b -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Lazy: foldrWithKey' :: (Word -> a -> b -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Lazy: insert :: Word -> a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: insertWith :: (a -> a) -> Word -> a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: intersection :: Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: intersectionL :: Patricia a -> Patricia b -> Patricia a
+ Data.Patricia.Word.Lazy: intersectionWith :: (a -> b -> c) -> Patricia a -> Patricia b -> Patricia c
+ Data.Patricia.Word.Lazy: intersectionWithKey :: (Word -> a -> b -> c) -> Patricia a -> Patricia b -> Patricia c
+ Data.Patricia.Word.Lazy: lookup :: Word -> Patricia a -> Maybe a
+ Data.Patricia.Word.Lazy: lookupL :: Word -> Patricia a -> Maybe (Lookup a)
+ Data.Patricia.Word.Lazy: lookupMax :: Patricia a -> Maybe a
+ Data.Patricia.Word.Lazy: lookupMaxWithKey :: Patricia a -> Maybe (Lookup a)
+ Data.Patricia.Word.Lazy: lookupMin :: Patricia a -> Maybe a
+ Data.Patricia.Word.Lazy: lookupMinWithKey :: Patricia a -> Maybe (Lookup a)
+ Data.Patricia.Word.Lazy: lookupR :: Word -> Patricia a -> Maybe (Lookup a)
+ Data.Patricia.Word.Lazy: map :: (a -> b) -> Patricia a -> Patricia b
+ Data.Patricia.Word.Lazy: mapEither :: (a -> Either b c) -> Patricia a -> (Patricia b, Patricia c)
+ Data.Patricia.Word.Lazy: mapEitherWithKey :: (Word -> a -> Either b c) -> Patricia a -> (Patricia b, Patricia c)
+ Data.Patricia.Word.Lazy: mapMaybe :: (a -> Maybe b) -> Patricia a -> Patricia b
+ Data.Patricia.Word.Lazy: mapMaybeWithKey :: (Word -> a -> Maybe b) -> Patricia a -> Patricia b
+ Data.Patricia.Word.Lazy: mapWithKey :: (Word -> a -> b) -> Patricia a -> Patricia b
+ Data.Patricia.Word.Lazy: maxView :: Patricia a -> Maybe (ViewR a)
+ Data.Patricia.Word.Lazy: member :: Word -> Patricia a -> Bool
+ Data.Patricia.Word.Lazy: minView :: Patricia a -> Maybe (ViewL a)
+ Data.Patricia.Word.Lazy: null :: Patricia a -> Bool
+ Data.Patricia.Word.Lazy: partition :: (a -> Bool) -> Patricia a -> (Patricia a, Patricia a)
+ Data.Patricia.Word.Lazy: partitionWithKey :: (Word -> a -> Bool) -> Patricia a -> (Patricia a, Patricia a)
+ Data.Patricia.Word.Lazy: pattern Range :: Word -> Word -> Range
+ Data.Patricia.Word.Lazy: singleton :: Word -> a -> Patricia a
+ Data.Patricia.Word.Lazy: size :: Patricia a -> Int
+ Data.Patricia.Word.Lazy: splitL :: Word -> Patricia a -> (Patricia a, Patricia a)
+ Data.Patricia.Word.Lazy: splitLookup :: Word -> Patricia a -> (Patricia a, Maybe a, Patricia a)
+ Data.Patricia.Word.Lazy: splitR :: Word -> Patricia a -> (Patricia a, Patricia a)
+ Data.Patricia.Word.Lazy: takeL :: Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: takeR :: Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: takeRange :: Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: toStrict :: LazyPatricia a -> StrictPatricia a
+ Data.Patricia.Word.Lazy: traverse :: Applicative f => (a -> f b) -> Patricia a -> f (Patricia b)
+ Data.Patricia.Word.Lazy: traverseWithKey :: Applicative f => (Word -> a -> f b) -> Patricia a -> f (Patricia b)
+ Data.Patricia.Word.Lazy: type LazyPatricia = Patricia
+ Data.Patricia.Word.Lazy: union :: Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: unionL :: Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: unionWith :: (a -> a -> a) -> Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: unionWithKey :: (Word -> a -> a -> a) -> Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: update :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: updateL :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: updateLWithKey :: (Word -> a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: updateMax :: (a -> Maybe a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: updateMaxWithKey :: (Word -> a -> Maybe a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: updateMin :: (a -> Maybe a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: updateMinWithKey :: (Word -> a -> Maybe a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: updateR :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: updateRWithKey :: (Word -> a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: updateRange :: (a -> Maybe a) -> Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy: updateRangeWithKey :: (Word -> a -> Maybe a) -> Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy.Debug: Invalid :: Reason -> Validity
+ Data.Patricia.Word.Lazy.Debug: KeyBelow :: Prefix -> Key -> Reason
+ Data.Patricia.Word.Lazy.Debug: MalformedBin :: Prefix -> Reason
+ Data.Patricia.Word.Lazy.Debug: PrefixBelow :: Prefix -> Prefix -> Reason
+ Data.Patricia.Word.Lazy.Debug: Valid :: Validity
+ Data.Patricia.Word.Lazy.Debug: ZeroPrefix :: Reason
+ Data.Patricia.Word.Lazy.Debug: data Reason
+ Data.Patricia.Word.Lazy.Debug: data Validity
+ Data.Patricia.Word.Lazy.Debug: showsTree :: (a -> ShowS) -> Patricia a -> ShowS
+ Data.Patricia.Word.Lazy.Debug: validate :: Patricia a -> Validity
+ Data.Patricia.Word.Lazy.TH: sequenceCode :: Quote m => Patricia (Code m a) -> Code m (Patricia a)
+ Data.Patricia.Word.Lazy.Unsafe: Bin :: {-# UNPACK #-} !Prefix -> Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy.Unsafe: Lookup :: {-# UNPACK #-} !Word -> a -> Lookup a
+ Data.Patricia.Word.Lazy.Unsafe: MalformedTree :: String -> String -> MalformedTree
+ Data.Patricia.Word.Lazy.Unsafe: Nil :: Patricia a
+ Data.Patricia.Word.Lazy.Unsafe: Tip :: {-# UNPACK #-} !Key -> a -> Patricia a
+ Data.Patricia.Word.Lazy.Unsafe: UnsafeRange :: {-# UNPACK #-} !Key -> {-# UNPACK #-} !Key -> Range
+ Data.Patricia.Word.Lazy.Unsafe: ViewL :: {-# UNPACK #-} !Lookup a -> !Patricia a -> ViewL a
+ Data.Patricia.Word.Lazy.Unsafe: ViewR :: !Patricia a -> {-# UNPACK #-} !Lookup a -> ViewR a
+ Data.Patricia.Word.Lazy.Unsafe: beyond :: Prefix -> Key -> Bool
+ Data.Patricia.Word.Lazy.Unsafe: branchingBit :: Prefix -> Prefix -> Mask
+ Data.Patricia.Word.Lazy.Unsafe: data Lookup a
+ Data.Patricia.Word.Lazy.Unsafe: data MalformedTree
+ Data.Patricia.Word.Lazy.Unsafe: data Patricia a
+ Data.Patricia.Word.Lazy.Unsafe: data Range
+ Data.Patricia.Word.Lazy.Unsafe: data ViewL a
+ Data.Patricia.Word.Lazy.Unsafe: data ViewR a
+ Data.Patricia.Word.Lazy.Unsafe: lower :: Prefix -> Key
+ Data.Patricia.Word.Lazy.Unsafe: mask :: Key -> Mask -> Word
+ Data.Patricia.Word.Lazy.Unsafe: merge :: (Key -> a -> b -> Patricia c) -> (Key -> a -> Patricia c) -> (Prefix -> Patricia a -> Patricia a -> Patricia c) -> (Key -> b -> Patricia c) -> (Prefix -> Patricia b -> Patricia b -> Patricia c) -> Patricia a -> Patricia b -> Patricia c
+ Data.Patricia.Word.Lazy.Unsafe: pattern Range :: Word -> Word -> Range
+ Data.Patricia.Word.Lazy.Unsafe: type Key = Word
+ Data.Patricia.Word.Lazy.Unsafe: type Mask = Word
+ Data.Patricia.Word.Lazy.Unsafe: type Prefix = Word
+ Data.Patricia.Word.Lazy.Unsafe: unsafeAdjustRange :: (a -> a) -> Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy.Unsafe: unsafeAdjustRangeWithKey :: (Word -> a -> a) -> Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy.Unsafe: unsafeDeleteRange :: Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy.Unsafe: unsafeLookupMax :: Patricia a -> (# a #)
+ Data.Patricia.Word.Lazy.Unsafe: unsafeLookupMaxWithKey :: Patricia a -> Lookup a
+ Data.Patricia.Word.Lazy.Unsafe: unsafeLookupMin :: Patricia a -> (# a #)
+ Data.Patricia.Word.Lazy.Unsafe: unsafeLookupMinWithKey :: Patricia a -> Lookup a
+ Data.Patricia.Word.Lazy.Unsafe: unsafeMaxView :: Patricia a -> ViewR a
+ Data.Patricia.Word.Lazy.Unsafe: unsafeMinView :: Patricia a -> ViewL a
+ Data.Patricia.Word.Lazy.Unsafe: unsafeTakeRange :: Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy.Unsafe: unsafeUpdateRange :: (a -> Maybe a) -> Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy.Unsafe: unsafeUpdateRangeWithKey :: (Word -> a -> Maybe a) -> Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Lazy.Unsafe: upper :: Prefix -> Key
+ Data.Patricia.Word.Lazy.Unsafe: zeroBit :: Key -> Mask -> Bool
+ Data.Patricia.Word.Strict: Equal :: PartialOrdering
+ Data.Patricia.Word.Strict: Incomparable :: PartialOrdering
+ Data.Patricia.Word.Strict: Lookup :: {-# UNPACK #-} !Word -> a -> Lookup a
+ Data.Patricia.Word.Strict: Split :: !Patricia l -> !Patricia r -> Split l r
+ Data.Patricia.Word.Strict: SplitLookup :: !Patricia l -> !Maybe x -> !Patricia r -> SplitLookup l x r
+ Data.Patricia.Word.Strict: Subset :: PartialOrdering
+ Data.Patricia.Word.Strict: Superset :: PartialOrdering
+ Data.Patricia.Word.Strict: ViewL :: {-# UNPACK #-} !Lookup a -> !Patricia a -> ViewL a
+ Data.Patricia.Word.Strict: ViewR :: !Patricia a -> {-# UNPACK #-} !Lookup a -> ViewR a
+ Data.Patricia.Word.Strict: adjust :: (a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjust' :: (a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustL :: (a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustL' :: (a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustLWithKey :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustLWithKey' :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustMax :: (a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustMax' :: (a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustMaxWithKey :: (Word -> a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustMaxWithKey' :: (Word -> a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustMin :: (a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustMin' :: (a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustMinWithKey :: (Word -> a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustMinWithKey' :: (Word -> a -> a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustR :: (a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustR' :: (a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustRWithKey :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustRWithKey' :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustRange :: (a -> a) -> Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustRange' :: (a -> a) -> Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustRangeWithKey :: (Word -> a -> a) -> Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: adjustRangeWithKey' :: (Word -> a -> a) -> Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: alter :: (Maybe a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: compare :: (a -> b -> Bool) -> Patricia a -> Patricia b -> PartialOrdering
+ Data.Patricia.Word.Strict: data Lookup a
+ Data.Patricia.Word.Strict: data PartialOrdering
+ Data.Patricia.Word.Strict: data Patricia a
+ Data.Patricia.Word.Strict: data Range
+ Data.Patricia.Word.Strict: data Split l r
+ Data.Patricia.Word.Strict: data SplitLookup l x r
+ Data.Patricia.Word.Strict: data ViewL a
+ Data.Patricia.Word.Strict: data ViewR a
+ Data.Patricia.Word.Strict: delete :: Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: deleteL :: Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: deleteMax :: Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: deleteMin :: Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: deleteR :: Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: deleteRange :: Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: difference :: Patricia a -> Patricia b -> Patricia a
+ Data.Patricia.Word.Strict: differenceWith :: (a -> b -> Maybe a) -> Patricia a -> Patricia b -> Patricia a
+ Data.Patricia.Word.Strict: differenceWithKey :: (Word -> a -> b -> Maybe a) -> Patricia a -> Patricia b -> Patricia a
+ Data.Patricia.Word.Strict: dirtyFind :: a -> Word -> Patricia a -> a
+ Data.Patricia.Word.Strict: dirtyLookup :: Word -> Patricia a -> Maybe a
+ Data.Patricia.Word.Strict: dirtyMember :: Word -> Patricia a -> Bool
+ Data.Patricia.Word.Strict: disjoint :: Patricia a -> Patricia b -> Bool
+ Data.Patricia.Word.Strict: empty :: Patricia a
+ Data.Patricia.Word.Strict: filter :: (a -> Bool) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: filterWithKey :: (Word -> a -> Bool) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: find :: a -> Word -> Patricia a -> a
+ Data.Patricia.Word.Strict: foldMap :: Monoid m => (a -> m) -> Patricia a -> m
+ Data.Patricia.Word.Strict: foldMapWithKey :: Monoid m => (Word -> a -> m) -> Patricia a -> m
+ Data.Patricia.Word.Strict: foldl :: (b -> a -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Strict: foldl' :: (b -> a -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Strict: foldlWithKey :: (b -> Word -> a -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Strict: foldlWithKey' :: (b -> Word -> a -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Strict: foldr :: (a -> b -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Strict: foldr' :: (a -> b -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Strict: foldrWithKey :: (Word -> a -> b -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Strict: foldrWithKey' :: (Word -> a -> b -> b) -> b -> Patricia a -> b
+ Data.Patricia.Word.Strict: insert :: Word -> a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: insertWith :: (a -> a) -> Word -> a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: insertWith' :: (a -> a) -> Word -> a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: intersection :: Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: intersectionL :: Patricia a -> Patricia b -> Patricia a
+ Data.Patricia.Word.Strict: intersectionWith' :: (a -> b -> c) -> Patricia a -> Patricia b -> Patricia c
+ Data.Patricia.Word.Strict: intersectionWithKey' :: (Word -> a -> b -> c) -> Patricia a -> Patricia b -> Patricia c
+ Data.Patricia.Word.Strict: lookup :: Word -> Patricia a -> Maybe a
+ Data.Patricia.Word.Strict: lookupL :: Word -> Patricia a -> Maybe (Lookup a)
+ Data.Patricia.Word.Strict: lookupMax :: Patricia a -> Maybe a
+ Data.Patricia.Word.Strict: lookupMaxWithKey :: Patricia a -> Maybe (Lookup a)
+ Data.Patricia.Word.Strict: lookupMin :: Patricia a -> Maybe a
+ Data.Patricia.Word.Strict: lookupMinWithKey :: Patricia a -> Maybe (Lookup a)
+ Data.Patricia.Word.Strict: lookupR :: Word -> Patricia a -> Maybe (Lookup a)
+ Data.Patricia.Word.Strict: map :: (a -> b) -> Patricia a -> Patricia b
+ Data.Patricia.Word.Strict: map' :: (a -> b) -> Patricia a -> Patricia b
+ Data.Patricia.Word.Strict: mapEither :: (a -> Either b c) -> Patricia a -> Split b c
+ Data.Patricia.Word.Strict: mapEitherWithKey :: (Word -> a -> Either b c) -> Patricia a -> Split b c
+ Data.Patricia.Word.Strict: mapMaybe :: (a -> Maybe b) -> Patricia a -> Patricia b
+ Data.Patricia.Word.Strict: mapMaybeWithKey :: (Word -> a -> Maybe b) -> Patricia a -> Patricia b
+ Data.Patricia.Word.Strict: mapWithKey :: (Word -> a -> b) -> Patricia a -> Patricia b
+ Data.Patricia.Word.Strict: mapWithKey' :: (Word -> a -> b) -> Patricia a -> Patricia b
+ Data.Patricia.Word.Strict: maxView :: Patricia a -> Maybe (ViewR a)
+ Data.Patricia.Word.Strict: member :: Word -> Patricia a -> Bool
+ Data.Patricia.Word.Strict: minView :: Patricia a -> Maybe (ViewL a)
+ Data.Patricia.Word.Strict: null :: Patricia a -> Bool
+ Data.Patricia.Word.Strict: partition :: (a -> Bool) -> Patricia a -> Split a a
+ Data.Patricia.Word.Strict: partitionWithKey :: (Word -> a -> Bool) -> Patricia a -> Split a a
+ Data.Patricia.Word.Strict: pattern Range :: Word -> Word -> Range
+ Data.Patricia.Word.Strict: singleton :: Word -> a -> Patricia a
+ Data.Patricia.Word.Strict: size :: Patricia a -> Int
+ Data.Patricia.Word.Strict: splitL :: Word -> Patricia a -> Split a a
+ Data.Patricia.Word.Strict: splitLookup :: Word -> Patricia a -> SplitLookup a a a
+ Data.Patricia.Word.Strict: splitR :: Word -> Patricia a -> Split a a
+ Data.Patricia.Word.Strict: takeL :: Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: takeR :: Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: takeRange :: Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: toLazy :: StrictPatricia a -> LazyPatricia a
+ Data.Patricia.Word.Strict: traverse :: Applicative f => (a -> f b) -> Patricia a -> f (Patricia b)
+ Data.Patricia.Word.Strict: traverseWithKey :: Applicative f => (Word -> a -> f b) -> Patricia a -> f (Patricia b)
+ Data.Patricia.Word.Strict: type StrictPatricia = Patricia
+ Data.Patricia.Word.Strict: union :: Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: unionL :: Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: unionWith' :: (a -> a -> a) -> Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: unionWithKey' :: (Word -> a -> a -> a) -> Patricia a -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: update :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: updateL :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: updateLWithKey :: (Word -> a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: updateMax :: (a -> Maybe a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: updateMaxWithKey :: (Word -> a -> Maybe a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: updateMin :: (a -> Maybe a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: updateMinWithKey :: (Word -> a -> Maybe a) -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: updateR :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: updateRWithKey :: (Word -> a -> Maybe a) -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: updateRange :: (a -> Maybe a) -> Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict: updateRangeWithKey :: (Word -> a -> Maybe a) -> Range -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict.Debug: Invalid :: Reason -> Validity
+ Data.Patricia.Word.Strict.Debug: KeyBelow :: Prefix -> Key -> Reason
+ Data.Patricia.Word.Strict.Debug: MalformedBin :: Prefix -> Reason
+ Data.Patricia.Word.Strict.Debug: PrefixBelow :: Prefix -> Prefix -> Reason
+ Data.Patricia.Word.Strict.Debug: Valid :: Validity
+ Data.Patricia.Word.Strict.Debug: ZeroPrefix :: Reason
+ Data.Patricia.Word.Strict.Debug: data Reason
+ Data.Patricia.Word.Strict.Debug: data Validity
+ Data.Patricia.Word.Strict.Debug: showsTree :: (a -> ShowS) -> Patricia a -> ShowS
+ Data.Patricia.Word.Strict.Debug: validate :: Patricia a -> Validity
+ Data.Patricia.Word.Strict.TH: sequenceCode :: Quote m => Patricia (Code m a) -> Code m (Patricia a)
+ Data.Patricia.Word.Strict.Unsafe: Bin :: {-# UNPACK #-} !Prefix -> !Patricia a -> !Patricia a -> Patricia a
+ Data.Patricia.Word.Strict.Unsafe: Lookup :: {-# UNPACK #-} !Word -> a -> Lookup a
+ Data.Patricia.Word.Strict.Unsafe: MalformedTree :: String -> String -> MalformedTree
+ Data.Patricia.Word.Strict.Unsafe: Nil :: Patricia a
+ Data.Patricia.Word.Strict.Unsafe: Tip :: {-# UNPACK #-} !Key -> a -> Patricia a
+ Data.Patricia.Word.Strict.Unsafe: UnsafeRange :: {-# UNPACK #-} !Key -> {-# UNPACK #-} !Key -> Range
+ Data.Patricia.Word.Strict.Unsafe: ViewL :: {-# UNPACK #-} !Lookup a -> !Patricia a -> ViewL a
+ Data.Patricia.Word.Strict.Unsafe: ViewR :: !Patricia a -> {-# UNPACK #-} !Lookup a -> ViewR a
+ Data.Patricia.Word.Strict.Unsafe: beyond :: Prefix -> Key -> Bool
+ Data.Patricia.Word.Strict.Unsafe: branchingBit :: Prefix -> Prefix -> Mask
+ Data.Patricia.Word.Strict.Unsafe: data Lookup a
+ Data.Patricia.Word.Strict.Unsafe: data MalformedTree
+ Data.Patricia.Word.Strict.Unsafe: data Patricia a
+ Data.Patricia.Word.Strict.Unsafe: data Range
+ Data.Patricia.Word.Strict.Unsafe: data ViewL a
+ Data.Patricia.Word.Strict.Unsafe: data ViewR a
+ Data.Patricia.Word.Strict.Unsafe: lower :: Prefix -> Key
+ Data.Patricia.Word.Strict.Unsafe: mask :: Key -> Mask -> Word
+ Data.Patricia.Word.Strict.Unsafe: merge :: (Key -> a -> b -> Patricia c) -> (Key -> a -> Patricia c) -> (Prefix -> Patricia a -> Patricia a -> Patricia c) -> (Key -> b -> Patricia c) -> (Prefix -> Patricia b -> Patricia b -> Patricia c) -> Patricia a -> Patricia b -> Patricia c
+ Data.Patricia.Word.Strict.Unsafe: pattern Range :: Word -> Word -> Range
+ Data.Patricia.Word.Strict.Unsafe: type Key = Word
+ Data.Patricia.Word.Strict.Unsafe: type Mask = Word
+ Data.Patricia.Word.Strict.Unsafe: type Prefix = Word
+ Data.Patricia.Word.Strict.Unsafe: unsafeAdjustRange :: (a -> a) -> Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict.Unsafe: unsafeAdjustRange' :: (a -> a) -> Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict.Unsafe: unsafeAdjustRangeWithKey :: (Word -> a -> a) -> Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict.Unsafe: unsafeAdjustRangeWithKey' :: (Word -> a -> a) -> Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict.Unsafe: unsafeDeleteRange :: Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict.Unsafe: unsafeLookupMax :: Patricia a -> (# a #)
+ Data.Patricia.Word.Strict.Unsafe: unsafeLookupMaxWithKey :: Patricia a -> Lookup a
+ Data.Patricia.Word.Strict.Unsafe: unsafeLookupMin :: Patricia a -> (# a #)
+ Data.Patricia.Word.Strict.Unsafe: unsafeLookupMinWithKey :: Patricia a -> Lookup a
+ Data.Patricia.Word.Strict.Unsafe: unsafeMaxView :: Patricia a -> ViewR a
+ Data.Patricia.Word.Strict.Unsafe: unsafeMinView :: Patricia a -> ViewL a
+ Data.Patricia.Word.Strict.Unsafe: unsafeTakeRange :: Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict.Unsafe: unsafeUpdateRange :: (a -> Maybe a) -> Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict.Unsafe: unsafeUpdateRangeWithKey :: (Word -> a -> Maybe a) -> Word -> Word -> Patricia a -> Patricia a
+ Data.Patricia.Word.Strict.Unsafe: upper :: Prefix -> Key
+ Data.Patricia.Word.Strict.Unsafe: zeroBit :: Key -> Mask -> Bool
+ Data.Radix1Tree.Word8.Key: buildByteString :: Build1 -> ByteString
+ Data.Radix1Tree.Word8.Key: buildBytes :: Build1 -> NonEmpty Word8
+ Data.Radix1Tree.Word8.Key: buildShortByteString :: Build1 -> ShortByteString
+ Data.Radix1Tree.Word8.Key: data Build1
+ Data.Radix1Tree.Word8.Key: data Feed1
+ Data.Radix1Tree.Word8.Key: feedBytes :: NonEmpty Word8 -> Feed1
+ Data.Radix1Tree.Word8.Key.Unsafe: (:/) :: Tsil a -> a -> YtpmeNon a
+ Data.Radix1Tree.Word8.Key.Unsafe: Build1 :: YtpmeNon ByteArray -> Build1
+ Data.Radix1Tree.Word8.Key.Unsafe: Done :: Step a b
+ Data.Radix1Tree.Word8.Key.Unsafe: Feed1 :: {-# UNPACK #-} !Word8 -> (forall a. (forall x. (x -> Step Word8 x) -> x -> a) -> a) -> Feed1
+ Data.Radix1Tree.Word8.Key.Unsafe: Lin :: Tsil a
+ Data.Radix1Tree.Word8.Key.Unsafe: More :: a -> b -> Step a b
+ Data.Radix1Tree.Word8.Key.Unsafe: Snoc :: Tsil a -> a -> Tsil a
+ Data.Radix1Tree.Word8.Key.Unsafe: data Feed1
+ Data.Radix1Tree.Word8.Key.Unsafe: data Step a b
+ Data.Radix1Tree.Word8.Key.Unsafe: data Tsil a
+ Data.Radix1Tree.Word8.Key.Unsafe: data YtpmeNon a
+ Data.Radix1Tree.Word8.Key.Unsafe: newtype Build1
+ Data.Radix1Tree.Word8.Key.Unsafe: unsafeBuildText :: Build1 -> Text
+ Data.Radix1Tree.Word8.Key.Unsafe: unsafeFeedByteString :: ByteString -> Feed1
+ Data.Radix1Tree.Word8.Key.Unsafe: unsafeFeedLazyByteString :: ByteString -> ByteString -> Feed1
+ Data.Radix1Tree.Word8.Key.Unsafe: unsafeFeedLazyText :: Text -> Text -> Feed1
+ Data.Radix1Tree.Word8.Key.Unsafe: unsafeFeedShortByteString :: ShortByteString -> Feed1
+ Data.Radix1Tree.Word8.Key.Unsafe: unsafeFeedText :: Text -> Feed1
+ Data.Radix1Tree.Word8.Lazy: Closed :: Openness
+ Data.Radix1Tree.Word8.Lazy: Equal :: PartialOrdering
+ Data.Radix1Tree.Word8.Lazy: Incomparable :: PartialOrdering
+ Data.Radix1Tree.Word8.Lazy: Inside :: Location
+ Data.Radix1Tree.Word8.Lazy: Lookup :: !Build -> a -> Lookup a
+ Data.Radix1Tree.Word8.Lazy: Open :: Openness
+ Data.Radix1Tree.Word8.Lazy: Outside :: Location
+ Data.Radix1Tree.Word8.Lazy: RadixTree :: {-# UNPACK #-} !Maybe a -> Radix1Tree a -> RadixTree a
+ Data.Radix1Tree.Word8.Lazy: Subset :: PartialOrdering
+ Data.Radix1Tree.Word8.Lazy: Superset :: PartialOrdering
+ Data.Radix1Tree.Word8.Lazy: ViewL :: !Build -> a -> !RadixTree a -> ViewL a
+ Data.Radix1Tree.Word8.Lazy: ViewR :: !RadixTree a -> !Build -> a -> ViewR a
+ Data.Radix1Tree.Word8.Lazy: adjust :: (a -> a) -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: adjustL :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: adjustLWithKey :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: adjustMax :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: adjustMaxWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: adjustMin :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: adjustMinWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: adjustR :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: adjustRWithKey :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: alter :: (Maybe a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: compare :: (a -> b -> Bool) -> Radix1Tree a -> Radix1Tree b -> PartialOrdering
+ Data.Radix1Tree.Word8.Lazy: cursor :: Radix1Tree a -> Cursor a
+ Data.Radix1Tree.Word8.Lazy: data Cursor a
+ Data.Radix1Tree.Word8.Lazy: data Location
+ Data.Radix1Tree.Word8.Lazy: data Lookup a
+ Data.Radix1Tree.Word8.Lazy: data Openness
+ Data.Radix1Tree.Word8.Lazy: data PartialOrdering
+ Data.Radix1Tree.Word8.Lazy: data Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: data RadixTree a
+ Data.Radix1Tree.Word8.Lazy: data ViewL a
+ Data.Radix1Tree.Word8.Lazy: data ViewR a
+ Data.Radix1Tree.Word8.Lazy: delete :: Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: deleteMax :: Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: deleteMin :: Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: difference :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: differenceWith :: (a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: differenceWithKey :: (Build1 -> a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: disjoint :: Radix1Tree a -> Radix1Tree b -> Bool
+ Data.Radix1Tree.Word8.Lazy: empty :: Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: filter :: (a -> Bool) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: filterWithKey :: (Build1 -> a -> Bool) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: find :: a -> Feed1 -> Radix1Tree a -> a
+ Data.Radix1Tree.Word8.Lazy: foldMap :: Monoid m => (a -> m) -> Radix1Tree a -> m
+ Data.Radix1Tree.Word8.Lazy: foldMapWithKey :: Monoid m => (Build1 -> a -> m) -> Radix1Tree a -> m
+ Data.Radix1Tree.Word8.Lazy: foldl :: (b -> a -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Lazy: foldl' :: (b -> a -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Lazy: foldlWithKey :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Lazy: foldlWithKey' :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Lazy: foldr :: (a -> b -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Lazy: foldr' :: (a -> b -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Lazy: foldrWithKey :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Lazy: foldrWithKey' :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Lazy: insert :: Feed1 -> a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: insertWith :: (a -> a) -> Feed1 -> a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: intersection :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: intersectionL :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: intersectionWith :: (a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c
+ Data.Radix1Tree.Word8.Lazy: intersectionWithKey :: (Build1 -> a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c
+ Data.Radix1Tree.Word8.Lazy: locate :: Cursor a -> Location
+ Data.Radix1Tree.Word8.Lazy: lookup :: Feed1 -> Radix1Tree a -> Maybe a
+ Data.Radix1Tree.Word8.Lazy: lookupL :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)
+ Data.Radix1Tree.Word8.Lazy: lookupMax :: Radix1Tree a -> Maybe a
+ Data.Radix1Tree.Word8.Lazy: lookupMaxWithKey :: Radix1Tree a -> Maybe (Lookup1 a)
+ Data.Radix1Tree.Word8.Lazy: lookupMin :: Radix1Tree a -> Maybe a
+ Data.Radix1Tree.Word8.Lazy: lookupMinWithKey :: Radix1Tree a -> Maybe (Lookup1 a)
+ Data.Radix1Tree.Word8.Lazy: lookupR :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)
+ Data.Radix1Tree.Word8.Lazy: map :: (a -> b) -> Radix1Tree a -> Radix1Tree b
+ Data.Radix1Tree.Word8.Lazy: mapEither :: (a -> Either b c) -> Radix1Tree a -> (Radix1Tree b, Radix1Tree c)
+ Data.Radix1Tree.Word8.Lazy: mapEitherWithKey :: (Build1 -> a -> Either b c) -> Radix1Tree a -> (Radix1Tree b, Radix1Tree c)
+ Data.Radix1Tree.Word8.Lazy: mapMaybe :: (a -> Maybe b) -> Radix1Tree a -> Radix1Tree b
+ Data.Radix1Tree.Word8.Lazy: mapMaybeWithKey :: (Build1 -> a -> Maybe b) -> Radix1Tree a -> Radix1Tree b
+ Data.Radix1Tree.Word8.Lazy: mapWithKey :: (Build1 -> a -> b) -> Radix1Tree a -> Radix1Tree b
+ Data.Radix1Tree.Word8.Lazy: maxView :: Radix1Tree a -> Maybe (ViewR1 a)
+ Data.Radix1Tree.Word8.Lazy: member :: Feed1 -> Radix1Tree a -> Bool
+ Data.Radix1Tree.Word8.Lazy: minView :: Radix1Tree a -> Maybe (ViewL1 a)
+ Data.Radix1Tree.Word8.Lazy: move :: Feed1 -> Cursor a -> Cursor a
+ Data.Radix1Tree.Word8.Lazy: null :: Radix1Tree a -> Bool
+ Data.Radix1Tree.Word8.Lazy: partition :: (a -> Bool) -> Radix1Tree a -> (Radix1Tree a, Radix1Tree a)
+ Data.Radix1Tree.Word8.Lazy: partitionWithKey :: (Build1 -> a -> Bool) -> Radix1Tree a -> (Radix1Tree a, Radix1Tree a)
+ Data.Radix1Tree.Word8.Lazy: prefix :: Feed1 -> RadixTree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: prune :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: shape :: (RadixTree a -> RadixTree a) -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: singleton :: Feed1 -> a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: size :: Radix1Tree a -> Int
+ Data.Radix1Tree.Word8.Lazy: splitL :: Openness -> Feed1 -> Radix1Tree a -> (Radix1Tree a, Radix1Tree a)
+ Data.Radix1Tree.Word8.Lazy: splitLookup :: Feed1 -> Radix1Tree a -> (Radix1Tree a, Maybe a, Radix1Tree a)
+ Data.Radix1Tree.Word8.Lazy: stop :: Cursor a -> Maybe a
+ Data.Radix1Tree.Word8.Lazy: subtree :: Feed1 -> Radix1Tree a -> RadixTree a
+ Data.Radix1Tree.Word8.Lazy: takeL :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: takeR :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: toStrict :: LazyRadix1Tree a -> StrictRadix1Tree a
+ Data.Radix1Tree.Word8.Lazy: traverse :: Applicative f => (a -> f b) -> Radix1Tree a -> f (Radix1Tree b)
+ Data.Radix1Tree.Word8.Lazy: traverseWithKey :: Applicative f => (Build1 -> a -> f b) -> Radix1Tree a -> f (Radix1Tree b)
+ Data.Radix1Tree.Word8.Lazy: type LazyRadix1Tree = Radix1Tree
+ Data.Radix1Tree.Word8.Lazy: union :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: unionL :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: unionWith :: (a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: unionWithKey :: (Build1 -> a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: update :: (a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: updateL :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: updateLWithKey :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: updateMax :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: updateMaxWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: updateMin :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: updateMinWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: updateR :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy: updateRWithKey :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Debug: EmptyByteArray :: Reason
+ Data.Radix1Tree.Word8.Lazy.Debug: Invalid :: Build -> Reason -> Validity
+ Data.Radix1Tree.Word8.Lazy.Debug: KeyBelow :: Prefix -> Key -> Reason
+ Data.Radix1Tree.Word8.Lazy.Debug: MalformedBin :: Prefix -> Reason
+ Data.Radix1Tree.Word8.Lazy.Debug: PrefixBelow :: Prefix -> Prefix -> Reason
+ Data.Radix1Tree.Word8.Lazy.Debug: UncompressedTip :: Reason
+ Data.Radix1Tree.Word8.Lazy.Debug: Valid :: Validity
+ Data.Radix1Tree.Word8.Lazy.Debug: ZeroPrefix :: Reason
+ Data.Radix1Tree.Word8.Lazy.Debug: data Reason
+ Data.Radix1Tree.Word8.Lazy.Debug: data Validity
+ Data.Radix1Tree.Word8.Lazy.Debug: showsTree :: (a -> ShowS) -> Radix1Tree a -> ShowS
+ Data.Radix1Tree.Word8.Lazy.Debug: validate :: Radix1Tree a -> Validity
+ Data.Radix1Tree.Word8.Lazy.TH: sequenceCode :: Quote m => Radix1Tree (Code m a) -> Code m (Radix1Tree a)
+ Data.Radix1Tree.Word8.Lazy.Unsafe: Bin :: {-# UNPACK #-} !Prefix -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: Lookup1 :: !Build1 -> a -> Lookup1 a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: MalformedTree :: String -> String -> MalformedTree
+ Data.Radix1Tree.Word8.Lazy.Unsafe: Nil :: Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: Tip :: {-# UNPACK #-} !ByteArray -> {-# UNPACK #-} !Maybe a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: ViewL1 :: !Build1 -> a -> !Radix1Tree a -> ViewL1 a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: ViewR1 :: !Radix1Tree a -> !Build1 -> a -> ViewR1 a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: beyond :: Prefix -> Key -> Bool
+ Data.Radix1Tree.Word8.Lazy.Unsafe: branchingBit :: Prefix -> Prefix -> Mask
+ Data.Radix1Tree.Word8.Lazy.Unsafe: data Lookup1 a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: data MalformedTree
+ Data.Radix1Tree.Word8.Lazy.Unsafe: data Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: data ViewL1 a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: data ViewR1 a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: lower :: Prefix -> Key
+ Data.Radix1Tree.Word8.Lazy.Unsafe: mask :: Key -> Mask -> Word
+ Data.Radix1Tree.Word8.Lazy.Unsafe: merge :: (Build1 -> a -> b -> Maybe c) -> (Build1 -> a -> Maybe c) -> (Build -> Radix1Tree a -> Radix1Tree c) -> (Build1 -> b -> Maybe c) -> (Build -> Radix1Tree b -> Radix1Tree c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c
+ Data.Radix1Tree.Word8.Lazy.Unsafe: type Key = Word
+ Data.Radix1Tree.Word8.Lazy.Unsafe: type Mask = Word
+ Data.Radix1Tree.Word8.Lazy.Unsafe: type Prefix = Word
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeAdjustMax :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeAdjustMaxWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeAdjustMin :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeAdjustMinWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeDeleteMax :: Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeDeleteMin :: Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeLookupMax :: Radix1Tree a -> (# a #)
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeLookupMaxWithKey :: Radix1Tree a -> Lookup1 a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeLookupMin :: Radix1Tree a -> (# a #)
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeLookupMinWithKey :: Radix1Tree a -> Lookup1 a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeMaxView :: Radix1Tree a -> ViewR1 a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeMinView :: Radix1Tree a -> ViewL1 a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeUpdateMax :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeUpdateMaxWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeUpdateMin :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: unsafeUpdateMinWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Lazy.Unsafe: upper :: Prefix -> Key
+ Data.Radix1Tree.Word8.Lazy.Unsafe: zeroBit :: Key -> Mask -> Bool
+ Data.Radix1Tree.Word8.Strict: Closed :: Openness
+ Data.Radix1Tree.Word8.Strict: Equal :: PartialOrdering
+ Data.Radix1Tree.Word8.Strict: Incomparable :: PartialOrdering
+ Data.Radix1Tree.Word8.Strict: Inside :: Location
+ Data.Radix1Tree.Word8.Strict: Lookup1 :: !Build1 -> a -> Lookup1 a
+ Data.Radix1Tree.Word8.Strict: Open :: Openness
+ Data.Radix1Tree.Word8.Strict: Outside :: Location
+ Data.Radix1Tree.Word8.Strict: RadixTree :: {-# UNPACK #-} !Maybe a -> !Radix1Tree a -> RadixTree a
+ Data.Radix1Tree.Word8.Strict: Split1 :: !Radix1Tree l -> !Radix1Tree r -> Split1 l r
+ Data.Radix1Tree.Word8.Strict: SplitLookup1 :: !Radix1Tree l -> !Maybe x -> !Radix1Tree r -> SplitLookup1 l x r
+ Data.Radix1Tree.Word8.Strict: Subset :: PartialOrdering
+ Data.Radix1Tree.Word8.Strict: Superset :: PartialOrdering
+ Data.Radix1Tree.Word8.Strict: ViewL1 :: !Build1 -> a -> !Radix1Tree a -> ViewL1 a
+ Data.Radix1Tree.Word8.Strict: ViewR1 :: !Radix1Tree a -> !Build1 -> a -> ViewR1 a
+ Data.Radix1Tree.Word8.Strict: adjust :: (a -> a) -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjust' :: (a -> a) -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustL :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustL' :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustLWithKey :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustLWithKey' :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustMax :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustMax' :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustMaxWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustMaxWithKey' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustMin :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustMin' :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustMinWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustMinWithKey' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustR :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustR' :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustRWithKey :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: adjustRWithKey' :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: alter :: (Maybe a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: compare :: (a -> b -> Bool) -> Radix1Tree a -> Radix1Tree b -> PartialOrdering
+ Data.Radix1Tree.Word8.Strict: cursor :: Radix1Tree a -> Cursor a
+ Data.Radix1Tree.Word8.Strict: data Cursor a
+ Data.Radix1Tree.Word8.Strict: data Location
+ Data.Radix1Tree.Word8.Strict: data Lookup1 a
+ Data.Radix1Tree.Word8.Strict: data Openness
+ Data.Radix1Tree.Word8.Strict: data PartialOrdering
+ Data.Radix1Tree.Word8.Strict: data Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: data RadixTree a
+ Data.Radix1Tree.Word8.Strict: data Split1 l r
+ Data.Radix1Tree.Word8.Strict: data SplitLookup1 l x r
+ Data.Radix1Tree.Word8.Strict: data ViewL1 a
+ Data.Radix1Tree.Word8.Strict: data ViewR1 a
+ Data.Radix1Tree.Word8.Strict: delete :: Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: deleteMax :: Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: deleteMin :: Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: difference :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: differenceWith :: (a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: differenceWithKey :: (Build1 -> a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: disjoint :: Radix1Tree a -> Radix1Tree b -> Bool
+ Data.Radix1Tree.Word8.Strict: empty :: Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: filter :: (a -> Bool) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: filterWithKey :: (Build1 -> a -> Bool) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: find :: a -> Feed1 -> Radix1Tree a -> a
+ Data.Radix1Tree.Word8.Strict: foldMap :: Monoid m => (a -> m) -> Radix1Tree a -> m
+ Data.Radix1Tree.Word8.Strict: foldMapWithKey :: Monoid m => (Build1 -> a -> m) -> Radix1Tree a -> m
+ Data.Radix1Tree.Word8.Strict: foldl :: (b -> a -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Strict: foldl' :: (b -> a -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Strict: foldlWithKey :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Strict: foldlWithKey' :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Strict: foldr :: (a -> b -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Strict: foldr' :: (a -> b -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Strict: foldrWithKey :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Strict: foldrWithKey' :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b
+ Data.Radix1Tree.Word8.Strict: insert :: Feed1 -> a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: insertWith :: (a -> a) -> Feed1 -> a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: insertWith' :: (a -> a) -> Feed1 -> a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: intersection :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: intersectionL :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: intersectionWith' :: (a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c
+ Data.Radix1Tree.Word8.Strict: intersectionWithKey' :: (Build1 -> a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c
+ Data.Radix1Tree.Word8.Strict: locate :: Cursor a -> Location
+ Data.Radix1Tree.Word8.Strict: lookup :: Feed1 -> Radix1Tree a -> Maybe a
+ Data.Radix1Tree.Word8.Strict: lookupL :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)
+ Data.Radix1Tree.Word8.Strict: lookupMax :: Radix1Tree a -> Maybe a
+ Data.Radix1Tree.Word8.Strict: lookupMaxWithKey :: Radix1Tree a -> Maybe (Lookup1 a)
+ Data.Radix1Tree.Word8.Strict: lookupMin :: Radix1Tree a -> Maybe a
+ Data.Radix1Tree.Word8.Strict: lookupMinWithKey :: Radix1Tree a -> Maybe (Lookup1 a)
+ Data.Radix1Tree.Word8.Strict: lookupR :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)
+ Data.Radix1Tree.Word8.Strict: map :: (a -> b) -> Radix1Tree a -> Radix1Tree b
+ Data.Radix1Tree.Word8.Strict: map' :: (a -> b) -> Radix1Tree a -> Radix1Tree b
+ Data.Radix1Tree.Word8.Strict: mapEither :: (a -> Either b c) -> Radix1Tree a -> Split1 b c
+ Data.Radix1Tree.Word8.Strict: mapEitherWithKey :: (Build1 -> a -> Either b c) -> Radix1Tree a -> Split1 b c
+ Data.Radix1Tree.Word8.Strict: mapMaybe :: (a -> Maybe b) -> Radix1Tree a -> Radix1Tree b
+ Data.Radix1Tree.Word8.Strict: mapMaybeWithKey :: (Build1 -> a -> Maybe b) -> Radix1Tree a -> Radix1Tree b
+ Data.Radix1Tree.Word8.Strict: mapWithKey :: (Build1 -> a -> b) -> Radix1Tree a -> Radix1Tree b
+ Data.Radix1Tree.Word8.Strict: mapWithKey' :: (Build1 -> a -> b) -> Radix1Tree a -> Radix1Tree b
+ Data.Radix1Tree.Word8.Strict: maxView :: Radix1Tree a -> Maybe (ViewR1 a)
+ Data.Radix1Tree.Word8.Strict: member :: Feed1 -> Radix1Tree a -> Bool
+ Data.Radix1Tree.Word8.Strict: minView :: Radix1Tree a -> Maybe (ViewL1 a)
+ Data.Radix1Tree.Word8.Strict: move :: Feed1 -> Cursor a -> Cursor a
+ Data.Radix1Tree.Word8.Strict: null :: Radix1Tree a -> Bool
+ Data.Radix1Tree.Word8.Strict: partition :: (a -> Bool) -> Radix1Tree a -> Split1 a a
+ Data.Radix1Tree.Word8.Strict: partitionWithKey :: (Build1 -> a -> Bool) -> Radix1Tree a -> Split1 a a
+ Data.Radix1Tree.Word8.Strict: prefix :: Feed1 -> RadixTree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: prune :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: shape :: (RadixTree a -> RadixTree a) -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: singleton :: Feed1 -> a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: size :: Radix1Tree a -> Int
+ Data.Radix1Tree.Word8.Strict: splitL :: Openness -> Feed1 -> Radix1Tree a -> Split1 a a
+ Data.Radix1Tree.Word8.Strict: splitLookup :: Feed1 -> Radix1Tree a -> SplitLookup1 a a a
+ Data.Radix1Tree.Word8.Strict: stop :: Cursor a -> Maybe a
+ Data.Radix1Tree.Word8.Strict: subtree :: Feed1 -> Radix1Tree a -> RadixTree a
+ Data.Radix1Tree.Word8.Strict: takeL :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: takeR :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: toLazy :: StrictRadix1Tree a -> LazyRadix1Tree a
+ Data.Radix1Tree.Word8.Strict: traverse :: Applicative f => (a -> f b) -> Radix1Tree a -> f (Radix1Tree b)
+ Data.Radix1Tree.Word8.Strict: traverseWithKey :: Applicative f => (Build1 -> a -> f b) -> Radix1Tree a -> f (Radix1Tree b)
+ Data.Radix1Tree.Word8.Strict: type StrictRadix1Tree = Radix1Tree
+ Data.Radix1Tree.Word8.Strict: union :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: unionL :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: unionWith' :: (a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: unionWithKey' :: (Build1 -> a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: update :: (a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: updateL :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: updateLWithKey :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: updateMax :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: updateMaxWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: updateMin :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: updateMinWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: updateR :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict: updateRWithKey :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Debug: EmptyByteArray :: Reason
+ Data.Radix1Tree.Word8.Strict.Debug: Invalid :: Build -> Reason -> Validity
+ Data.Radix1Tree.Word8.Strict.Debug: KeyBelow :: Prefix -> Key -> Reason
+ Data.Radix1Tree.Word8.Strict.Debug: MalformedBin :: Prefix -> Reason
+ Data.Radix1Tree.Word8.Strict.Debug: PrefixBelow :: Prefix -> Prefix -> Reason
+ Data.Radix1Tree.Word8.Strict.Debug: UncompressedTip :: Reason
+ Data.Radix1Tree.Word8.Strict.Debug: Valid :: Validity
+ Data.Radix1Tree.Word8.Strict.Debug: ZeroPrefix :: Reason
+ Data.Radix1Tree.Word8.Strict.Debug: data Reason
+ Data.Radix1Tree.Word8.Strict.Debug: data Validity
+ Data.Radix1Tree.Word8.Strict.Debug: showsTree :: (a -> ShowS) -> Radix1Tree a -> ShowS
+ Data.Radix1Tree.Word8.Strict.Debug: validate :: Radix1Tree a -> Validity
+ Data.Radix1Tree.Word8.Strict.TH: sequenceCode :: Quote m => Radix1Tree (Code m a) -> Code m (Radix1Tree a)
+ Data.Radix1Tree.Word8.Strict.Unsafe: Bin :: {-# UNPACK #-} !Prefix -> !Radix1Tree a -> !Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: Lookup1 :: !Build1 -> a -> Lookup1 a
+ Data.Radix1Tree.Word8.Strict.Unsafe: MalformedTree :: String -> String -> MalformedTree
+ Data.Radix1Tree.Word8.Strict.Unsafe: Nil :: Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: Tip :: {-# UNPACK #-} !ByteArray -> {-# UNPACK #-} !Maybe a -> !Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: ViewL1 :: !Build1 -> a -> !Radix1Tree a -> ViewL1 a
+ Data.Radix1Tree.Word8.Strict.Unsafe: ViewR1 :: !Radix1Tree a -> !Build1 -> a -> ViewR1 a
+ Data.Radix1Tree.Word8.Strict.Unsafe: beyond :: Prefix -> Key -> Bool
+ Data.Radix1Tree.Word8.Strict.Unsafe: branchingBit :: Prefix -> Prefix -> Mask
+ Data.Radix1Tree.Word8.Strict.Unsafe: data Lookup1 a
+ Data.Radix1Tree.Word8.Strict.Unsafe: data MalformedTree
+ Data.Radix1Tree.Word8.Strict.Unsafe: data Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: data ViewL1 a
+ Data.Radix1Tree.Word8.Strict.Unsafe: data ViewR1 a
+ Data.Radix1Tree.Word8.Strict.Unsafe: lower :: Prefix -> Key
+ Data.Radix1Tree.Word8.Strict.Unsafe: mask :: Key -> Mask -> Word
+ Data.Radix1Tree.Word8.Strict.Unsafe: merge :: (Build1 -> a -> b -> Maybe c) -> (Build1 -> a -> Maybe c) -> (Build -> Radix1Tree a -> Radix1Tree c) -> (Build1 -> b -> Maybe c) -> (Build -> Radix1Tree b -> Radix1Tree c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c
+ Data.Radix1Tree.Word8.Strict.Unsafe: type Key = Word
+ Data.Radix1Tree.Word8.Strict.Unsafe: type Mask = Word
+ Data.Radix1Tree.Word8.Strict.Unsafe: type Prefix = Word
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeAdjustMax :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeAdjustMax' :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeAdjustMaxWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeAdjustMaxWithKey' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeAdjustMin :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeAdjustMin' :: (a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeAdjustMinWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeAdjustMinWithKey' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeDeleteMax :: Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeDeleteMin :: Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeLookupMax :: Radix1Tree a -> (# a #)
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeLookupMaxWithKey :: Radix1Tree a -> Lookup1 a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeLookupMin :: Radix1Tree a -> (# a #)
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeLookupMinWithKey :: Radix1Tree a -> Lookup1 a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeMaxView :: Radix1Tree a -> ViewR1 a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeMinView :: Radix1Tree a -> ViewL1 a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeUpdateMax :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeUpdateMaxWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeUpdateMin :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: unsafeUpdateMinWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a
+ Data.Radix1Tree.Word8.Strict.Unsafe: upper :: Prefix -> Key
+ Data.Radix1Tree.Word8.Strict.Unsafe: zeroBit :: Key -> Mask -> Bool
+ Data.RadixTree.Word8.Key: buildByteString :: Build -> ByteString
+ Data.RadixTree.Word8.Key: buildBytes :: Build -> [Word8]
+ Data.RadixTree.Word8.Key: buildShortByteString :: Build -> ShortByteString
+ Data.RadixTree.Word8.Key: data Build
+ Data.RadixTree.Word8.Key: data Feed
+ Data.RadixTree.Word8.Key: feedByteString :: ByteString -> Feed
+ Data.RadixTree.Word8.Key: feedBytes :: [Word8] -> Feed
+ Data.RadixTree.Word8.Key: feedLazyByteString :: ByteString -> Feed
+ Data.RadixTree.Word8.Key: feedLazyText :: Text -> Feed
+ Data.RadixTree.Word8.Key: feedShortByteString :: ShortByteString -> Feed
+ Data.RadixTree.Word8.Key: feedText :: Text -> Feed
+ Data.RadixTree.Word8.Key.Unsafe: Build :: Tsil ByteArray -> Build
+ Data.RadixTree.Word8.Key.Unsafe: Done :: Step a b
+ Data.RadixTree.Word8.Key.Unsafe: Feed :: (forall a. (forall x. (x -> Step Word8 x) -> x -> a) -> a) -> Feed
+ Data.RadixTree.Word8.Key.Unsafe: Lin :: Tsil a
+ Data.RadixTree.Word8.Key.Unsafe: More :: a -> b -> Step a b
+ Data.RadixTree.Word8.Key.Unsafe: Snoc :: Tsil a -> a -> Tsil a
+ Data.RadixTree.Word8.Key.Unsafe: data Step a b
+ Data.RadixTree.Word8.Key.Unsafe: data Tsil a
+ Data.RadixTree.Word8.Key.Unsafe: newtype Build
+ Data.RadixTree.Word8.Key.Unsafe: newtype Feed
+ Data.RadixTree.Word8.Key.Unsafe: unsafeBuildText :: Build -> Text
+ Data.RadixTree.Word8.Lazy: Closed :: Openness
+ Data.RadixTree.Word8.Lazy: Equal :: PartialOrdering
+ Data.RadixTree.Word8.Lazy: Incomparable :: PartialOrdering
+ Data.RadixTree.Word8.Lazy: Inside :: Location
+ Data.RadixTree.Word8.Lazy: Lookup :: !Build -> a -> Lookup a
+ Data.RadixTree.Word8.Lazy: Open :: Openness
+ Data.RadixTree.Word8.Lazy: Outside :: Location
+ Data.RadixTree.Word8.Lazy: RadixTree :: {-# UNPACK #-} !Maybe a -> Radix1Tree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: Subset :: PartialOrdering
+ Data.RadixTree.Word8.Lazy: Superset :: PartialOrdering
+ Data.RadixTree.Word8.Lazy: ViewL :: !Build -> a -> !RadixTree a -> ViewL a
+ Data.RadixTree.Word8.Lazy: ViewR :: !RadixTree a -> !Build -> a -> ViewR a
+ Data.RadixTree.Word8.Lazy: adjust :: (a -> a) -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: adjustL :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: adjustLWithKey :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: adjustMax :: (a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: adjustMaxWithKey :: (Build -> a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: adjustMin :: (a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: adjustMinWithKey :: (Build -> a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: adjustR :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: adjustRWithKey :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: alter :: (Maybe a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: compare :: (a -> b -> Bool) -> RadixTree a -> RadixTree b -> PartialOrdering
+ Data.RadixTree.Word8.Lazy: cursor :: RadixTree a -> Cursor a
+ Data.RadixTree.Word8.Lazy: data Cursor a
+ Data.RadixTree.Word8.Lazy: data Location
+ Data.RadixTree.Word8.Lazy: data Lookup a
+ Data.RadixTree.Word8.Lazy: data Openness
+ Data.RadixTree.Word8.Lazy: data PartialOrdering
+ Data.RadixTree.Word8.Lazy: data RadixTree a
+ Data.RadixTree.Word8.Lazy: data ViewL a
+ Data.RadixTree.Word8.Lazy: data ViewR a
+ Data.RadixTree.Word8.Lazy: delete :: Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: deleteMax :: RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: deleteMin :: RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: difference :: RadixTree a -> RadixTree b -> RadixTree a
+ Data.RadixTree.Word8.Lazy: differenceWith :: (a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a
+ Data.RadixTree.Word8.Lazy: differenceWithKey :: (Build -> a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a
+ Data.RadixTree.Word8.Lazy: disjoint :: RadixTree a -> RadixTree b -> Bool
+ Data.RadixTree.Word8.Lazy: empty :: RadixTree a
+ Data.RadixTree.Word8.Lazy: filter :: (a -> Bool) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: filterWithKey :: (Build -> a -> Bool) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: find :: a -> Feed -> RadixTree a -> a
+ Data.RadixTree.Word8.Lazy: foldMap :: Monoid m => (a -> m) -> RadixTree a -> m
+ Data.RadixTree.Word8.Lazy: foldMapWithKey :: Monoid m => (Build -> a -> m) -> RadixTree a -> m
+ Data.RadixTree.Word8.Lazy: foldl :: (b -> a -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Lazy: foldl' :: (b -> a -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Lazy: foldlWithKey :: (b -> Build -> a -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Lazy: foldlWithKey' :: (b -> Build -> a -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Lazy: foldr :: (a -> b -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Lazy: foldr' :: (a -> b -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Lazy: foldrWithKey :: (Build -> a -> b -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Lazy: foldrWithKey' :: (Build -> a -> b -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Lazy: insert :: Feed -> a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: insertWith :: (a -> a) -> Feed -> a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: intersection :: RadixTree a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: intersectionL :: RadixTree a -> RadixTree b -> RadixTree a
+ Data.RadixTree.Word8.Lazy: intersectionWith :: (a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c
+ Data.RadixTree.Word8.Lazy: intersectionWithKey :: (Build -> a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c
+ Data.RadixTree.Word8.Lazy: locate :: Cursor a -> Location
+ Data.RadixTree.Word8.Lazy: lookup :: Feed -> RadixTree a -> Maybe a
+ Data.RadixTree.Word8.Lazy: lookupL :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)
+ Data.RadixTree.Word8.Lazy: lookupMax :: RadixTree a -> Maybe a
+ Data.RadixTree.Word8.Lazy: lookupMaxWithKey :: RadixTree a -> Maybe (Lookup a)
+ Data.RadixTree.Word8.Lazy: lookupMin :: RadixTree a -> Maybe a
+ Data.RadixTree.Word8.Lazy: lookupMinWithKey :: RadixTree a -> Maybe (Lookup a)
+ Data.RadixTree.Word8.Lazy: lookupR :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)
+ Data.RadixTree.Word8.Lazy: map :: (a -> b) -> RadixTree a -> RadixTree b
+ Data.RadixTree.Word8.Lazy: mapEither :: (a -> Either b c) -> RadixTree a -> (RadixTree b, RadixTree c)
+ Data.RadixTree.Word8.Lazy: mapEitherWithKey :: (Build -> a -> Either b c) -> RadixTree a -> (RadixTree b, RadixTree c)
+ Data.RadixTree.Word8.Lazy: mapMaybe :: (a -> Maybe b) -> RadixTree a -> RadixTree b
+ Data.RadixTree.Word8.Lazy: mapMaybeWithKey :: (Build -> a -> Maybe b) -> RadixTree a -> RadixTree b
+ Data.RadixTree.Word8.Lazy: mapWithKey :: (Build -> a -> b) -> RadixTree a -> RadixTree b
+ Data.RadixTree.Word8.Lazy: maxView :: RadixTree a -> Maybe (ViewR a)
+ Data.RadixTree.Word8.Lazy: member :: Feed -> RadixTree a -> Bool
+ Data.RadixTree.Word8.Lazy: minView :: RadixTree a -> Maybe (ViewL a)
+ Data.RadixTree.Word8.Lazy: move :: Feed -> Cursor a -> Cursor a
+ Data.RadixTree.Word8.Lazy: null :: RadixTree a -> Bool
+ Data.RadixTree.Word8.Lazy: partition :: (a -> Bool) -> RadixTree a -> (RadixTree a, RadixTree a)
+ Data.RadixTree.Word8.Lazy: partitionWithKey :: (Build -> a -> Bool) -> RadixTree a -> (RadixTree a, RadixTree a)
+ Data.RadixTree.Word8.Lazy: prefix :: Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: prune :: Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: shape :: (RadixTree a -> RadixTree a) -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: singleton :: Feed -> a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: size :: RadixTree a -> Int
+ Data.RadixTree.Word8.Lazy: splitL :: Openness -> Feed -> RadixTree a -> (RadixTree a, RadixTree a)
+ Data.RadixTree.Word8.Lazy: splitLookup :: Feed -> RadixTree a -> (RadixTree a, Maybe a, RadixTree a)
+ Data.RadixTree.Word8.Lazy: stop :: Cursor a -> Maybe a
+ Data.RadixTree.Word8.Lazy: subtree :: Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: takeL :: Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: takeR :: Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: toStrict :: LazyRadixTree a -> StrictRadixTree a
+ Data.RadixTree.Word8.Lazy: traverse :: Applicative f => (a -> f b) -> RadixTree a -> f (RadixTree b)
+ Data.RadixTree.Word8.Lazy: traverseWithKey :: Applicative f => (Build -> a -> f b) -> RadixTree a -> f (RadixTree b)
+ Data.RadixTree.Word8.Lazy: type LazyRadixTree = RadixTree
+ Data.RadixTree.Word8.Lazy: union :: RadixTree a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: unionL :: RadixTree a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: unionWith :: (a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: unionWithKey :: (Build -> a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: update :: (a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: updateL :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: updateLWithKey :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: updateMax :: (a -> Maybe a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: updateMaxWithKey :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: updateMin :: (a -> Maybe a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: updateMinWithKey :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: updateR :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy: updateRWithKey :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy.Debug: EmptyByteArray :: Reason
+ Data.RadixTree.Word8.Lazy.Debug: Invalid :: Build -> Reason -> Validity
+ Data.RadixTree.Word8.Lazy.Debug: KeyBelow :: Prefix -> Key -> Reason
+ Data.RadixTree.Word8.Lazy.Debug: MalformedBin :: Prefix -> Reason
+ Data.RadixTree.Word8.Lazy.Debug: PrefixBelow :: Prefix -> Prefix -> Reason
+ Data.RadixTree.Word8.Lazy.Debug: UncompressedTip :: Reason
+ Data.RadixTree.Word8.Lazy.Debug: Valid :: Validity
+ Data.RadixTree.Word8.Lazy.Debug: ZeroPrefix :: Reason
+ Data.RadixTree.Word8.Lazy.Debug: data Reason
+ Data.RadixTree.Word8.Lazy.Debug: data Validity
+ Data.RadixTree.Word8.Lazy.Debug: showsTree :: (a -> ShowS) -> RadixTree a -> ShowS
+ Data.RadixTree.Word8.Lazy.Debug: validate :: RadixTree a -> Validity
+ Data.RadixTree.Word8.Lazy.TH: sequenceCode :: Quote m => RadixTree (Code m a) -> Code m (RadixTree a)
+ Data.RadixTree.Word8.Lazy.Unsafe: Bin :: {-# UNPACK #-} !Prefix -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a
+ Data.RadixTree.Word8.Lazy.Unsafe: MalformedTree :: String -> String -> MalformedTree
+ Data.RadixTree.Word8.Lazy.Unsafe: Nil :: Radix1Tree a
+ Data.RadixTree.Word8.Lazy.Unsafe: RadixTree :: {-# UNPACK #-} !Maybe a -> Radix1Tree a -> RadixTree a
+ Data.RadixTree.Word8.Lazy.Unsafe: Tip :: {-# UNPACK #-} !ByteArray -> {-# UNPACK #-} !Maybe a -> Radix1Tree a -> Radix1Tree a
+ Data.RadixTree.Word8.Lazy.Unsafe: beyond :: Prefix -> Key -> Bool
+ Data.RadixTree.Word8.Lazy.Unsafe: branchingBit :: Prefix -> Prefix -> Mask
+ Data.RadixTree.Word8.Lazy.Unsafe: data MalformedTree
+ Data.RadixTree.Word8.Lazy.Unsafe: data Radix1Tree a
+ Data.RadixTree.Word8.Lazy.Unsafe: data RadixTree a
+ Data.RadixTree.Word8.Lazy.Unsafe: lower :: Prefix -> Key
+ Data.RadixTree.Word8.Lazy.Unsafe: mask :: Key -> Mask -> Prefix
+ Data.RadixTree.Word8.Lazy.Unsafe: merge :: (Build -> a -> b -> Maybe c) -> (Build -> a -> Maybe c) -> (Build -> Radix1Tree a -> Radix1Tree c) -> (Build -> b -> Maybe c) -> (Build -> Radix1Tree b -> Radix1Tree c) -> RadixTree a -> RadixTree b -> RadixTree c
+ Data.RadixTree.Word8.Lazy.Unsafe: type Key = Word8
+ Data.RadixTree.Word8.Lazy.Unsafe: type Mask = Word8
+ Data.RadixTree.Word8.Lazy.Unsafe: type Prefix = Word8
+ Data.RadixTree.Word8.Lazy.Unsafe: upper :: Prefix -> Key
+ Data.RadixTree.Word8.Lazy.Unsafe: zeroBit :: Key -> Mask -> Bool
+ Data.RadixTree.Word8.Strict: Closed :: Openness
+ Data.RadixTree.Word8.Strict: Equal :: PartialOrdering
+ Data.RadixTree.Word8.Strict: Incomparable :: PartialOrdering
+ Data.RadixTree.Word8.Strict: Inside :: Location
+ Data.RadixTree.Word8.Strict: Lookup :: !Build -> a -> Lookup a
+ Data.RadixTree.Word8.Strict: Open :: Openness
+ Data.RadixTree.Word8.Strict: Outside :: Location
+ Data.RadixTree.Word8.Strict: RadixTree :: {-# UNPACK #-} !Maybe a -> !Radix1Tree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: Split :: !RadixTree l -> !RadixTree r -> Split l r
+ Data.RadixTree.Word8.Strict: SplitLookup :: !RadixTree l -> !Maybe x -> !RadixTree r -> SplitLookup l x r
+ Data.RadixTree.Word8.Strict: Subset :: PartialOrdering
+ Data.RadixTree.Word8.Strict: Superset :: PartialOrdering
+ Data.RadixTree.Word8.Strict: ViewL :: !Build -> a -> !RadixTree a -> ViewL a
+ Data.RadixTree.Word8.Strict: ViewR :: !RadixTree a -> !Build -> a -> ViewR a
+ Data.RadixTree.Word8.Strict: adjust :: (a -> a) -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjust' :: (a -> a) -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustL :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustL' :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustLWithKey :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustLWithKey' :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustMax :: (a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustMax' :: (a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustMaxWithKey :: (Build -> a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustMaxWithKey' :: (Build -> a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustMin :: (a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustMin' :: (a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustMinWithKey :: (Build -> a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustMinWithKey' :: (Build -> a -> a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustR :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustR' :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustRWithKey :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: adjustRWithKey' :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: alter :: (Maybe a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: compare :: (a -> b -> Bool) -> RadixTree a -> RadixTree b -> PartialOrdering
+ Data.RadixTree.Word8.Strict: cursor :: RadixTree a -> Cursor a
+ Data.RadixTree.Word8.Strict: data Cursor a
+ Data.RadixTree.Word8.Strict: data Location
+ Data.RadixTree.Word8.Strict: data Lookup a
+ Data.RadixTree.Word8.Strict: data Openness
+ Data.RadixTree.Word8.Strict: data PartialOrdering
+ Data.RadixTree.Word8.Strict: data RadixTree a
+ Data.RadixTree.Word8.Strict: data Split l r
+ Data.RadixTree.Word8.Strict: data SplitLookup l x r
+ Data.RadixTree.Word8.Strict: data ViewL a
+ Data.RadixTree.Word8.Strict: data ViewR a
+ Data.RadixTree.Word8.Strict: delete :: Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: deleteMax :: RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: deleteMin :: RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: difference :: RadixTree a -> RadixTree b -> RadixTree a
+ Data.RadixTree.Word8.Strict: differenceWith :: (a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a
+ Data.RadixTree.Word8.Strict: differenceWithKey :: (Build -> a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a
+ Data.RadixTree.Word8.Strict: disjoint :: RadixTree a -> RadixTree b -> Bool
+ Data.RadixTree.Word8.Strict: empty :: RadixTree a
+ Data.RadixTree.Word8.Strict: filter :: (a -> Bool) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: filterWithKey :: (Build -> a -> Bool) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: find :: a -> Feed -> RadixTree a -> a
+ Data.RadixTree.Word8.Strict: foldMap :: Monoid m => (a -> m) -> RadixTree a -> m
+ Data.RadixTree.Word8.Strict: foldMapWithKey :: Monoid m => (Build -> a -> m) -> RadixTree a -> m
+ Data.RadixTree.Word8.Strict: foldl :: (b -> a -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Strict: foldl' :: (b -> a -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Strict: foldlWithKey :: (b -> Build -> a -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Strict: foldlWithKey' :: (b -> Build -> a -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Strict: foldr :: (a -> b -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Strict: foldr' :: (a -> b -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Strict: foldrWithKey :: (Build -> a -> b -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Strict: foldrWithKey' :: (Build -> a -> b -> b) -> b -> RadixTree a -> b
+ Data.RadixTree.Word8.Strict: insert :: Feed -> a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: insertWith :: (a -> a) -> Feed -> a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: insertWith' :: (a -> a) -> Feed -> a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: intersection :: RadixTree a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: intersectionL :: RadixTree a -> RadixTree b -> RadixTree a
+ Data.RadixTree.Word8.Strict: intersectionWith' :: (a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c
+ Data.RadixTree.Word8.Strict: intersectionWithKey' :: (Build -> a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c
+ Data.RadixTree.Word8.Strict: locate :: Cursor a -> Location
+ Data.RadixTree.Word8.Strict: lookup :: Feed -> RadixTree a -> Maybe a
+ Data.RadixTree.Word8.Strict: lookupL :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)
+ Data.RadixTree.Word8.Strict: lookupMax :: RadixTree a -> Maybe a
+ Data.RadixTree.Word8.Strict: lookupMaxWithKey :: RadixTree a -> Maybe (Lookup a)
+ Data.RadixTree.Word8.Strict: lookupMin :: RadixTree a -> Maybe a
+ Data.RadixTree.Word8.Strict: lookupMinWithKey :: RadixTree a -> Maybe (Lookup a)
+ Data.RadixTree.Word8.Strict: lookupR :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)
+ Data.RadixTree.Word8.Strict: map :: (a -> b) -> RadixTree a -> RadixTree b
+ Data.RadixTree.Word8.Strict: map' :: (a -> b) -> RadixTree a -> RadixTree b
+ Data.RadixTree.Word8.Strict: mapEither :: (a -> Either b c) -> RadixTree a -> Split b c
+ Data.RadixTree.Word8.Strict: mapEitherWithKey :: (Build -> a -> Either b c) -> RadixTree a -> Split b c
+ Data.RadixTree.Word8.Strict: mapMaybe :: (a -> Maybe b) -> RadixTree a -> RadixTree b
+ Data.RadixTree.Word8.Strict: mapMaybeWithKey :: (Build -> a -> Maybe b) -> RadixTree a -> RadixTree b
+ Data.RadixTree.Word8.Strict: mapWithKey :: (Build -> a -> b) -> RadixTree a -> RadixTree b
+ Data.RadixTree.Word8.Strict: mapWithKey' :: (Build -> a -> b) -> RadixTree a -> RadixTree b
+ Data.RadixTree.Word8.Strict: maxView :: RadixTree a -> Maybe (ViewR a)
+ Data.RadixTree.Word8.Strict: member :: Feed -> RadixTree a -> Bool
+ Data.RadixTree.Word8.Strict: minView :: RadixTree a -> Maybe (ViewL a)
+ Data.RadixTree.Word8.Strict: move :: Feed -> Cursor a -> Cursor a
+ Data.RadixTree.Word8.Strict: null :: RadixTree a -> Bool
+ Data.RadixTree.Word8.Strict: partition :: (a -> Bool) -> RadixTree a -> Split a a
+ Data.RadixTree.Word8.Strict: partitionWithKey :: (Build -> a -> Bool) -> RadixTree a -> Split a a
+ Data.RadixTree.Word8.Strict: prefix :: Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: prune :: Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: shape :: (RadixTree a -> RadixTree a) -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: singleton :: Feed -> a -> RadixTree a
+ Data.RadixTree.Word8.Strict: size :: RadixTree a -> Int
+ Data.RadixTree.Word8.Strict: splitL :: Openness -> Feed -> RadixTree a -> Split a a
+ Data.RadixTree.Word8.Strict: splitLookup :: Feed -> RadixTree a -> SplitLookup a a a
+ Data.RadixTree.Word8.Strict: stop :: Cursor a -> Maybe a
+ Data.RadixTree.Word8.Strict: subtree :: Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: takeL :: Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: takeR :: Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: toLazy :: StrictRadixTree a -> LazyRadixTree a
+ Data.RadixTree.Word8.Strict: traverse :: Applicative f => (a -> f b) -> RadixTree a -> f (RadixTree b)
+ Data.RadixTree.Word8.Strict: traverseWithKey :: Applicative f => (Build -> a -> f b) -> RadixTree a -> f (RadixTree b)
+ Data.RadixTree.Word8.Strict: type StrictRadixTree = RadixTree
+ Data.RadixTree.Word8.Strict: union :: RadixTree a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: unionL :: RadixTree a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: unionWith' :: (a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: unionWithKey' :: (Build -> a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: update :: (a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: updateL :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: updateLWithKey :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: updateMax :: (a -> Maybe a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: updateMaxWithKey :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: updateMin :: (a -> Maybe a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: updateMinWithKey :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: updateR :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict: updateRWithKey :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a
+ Data.RadixTree.Word8.Strict.Debug: EmptyByteArray :: Reason
+ Data.RadixTree.Word8.Strict.Debug: Invalid :: Build -> Reason -> Validity
+ Data.RadixTree.Word8.Strict.Debug: KeyBelow :: Prefix -> Key -> Reason
+ Data.RadixTree.Word8.Strict.Debug: MalformedBin :: Prefix -> Reason
+ Data.RadixTree.Word8.Strict.Debug: PrefixBelow :: Prefix -> Prefix -> Reason
+ Data.RadixTree.Word8.Strict.Debug: UncompressedTip :: Reason
+ Data.RadixTree.Word8.Strict.Debug: Valid :: Validity
+ Data.RadixTree.Word8.Strict.Debug: ZeroPrefix :: Reason
+ Data.RadixTree.Word8.Strict.Debug: data Reason
+ Data.RadixTree.Word8.Strict.Debug: data Validity
+ Data.RadixTree.Word8.Strict.Debug: showsTree :: (a -> ShowS) -> RadixTree a -> ShowS
+ Data.RadixTree.Word8.Strict.Debug: validate :: RadixTree a -> Validity
+ Data.RadixTree.Word8.Strict.TH: sequenceCode :: Quote m => RadixTree (Code m a) -> Code m (RadixTree a)
+ Data.RadixTree.Word8.Strict.Unsafe: Bin :: {-# UNPACK #-} !Prefix -> !Radix1Tree a -> !Radix1Tree a -> Radix1Tree a
+ Data.RadixTree.Word8.Strict.Unsafe: MalformedTree :: String -> String -> MalformedTree
+ Data.RadixTree.Word8.Strict.Unsafe: Nil :: Radix1Tree a
+ Data.RadixTree.Word8.Strict.Unsafe: RadixTree :: {-# UNPACK #-} !Maybe a -> !Radix1Tree a -> RadixTree a
+ Data.RadixTree.Word8.Strict.Unsafe: Tip :: {-# UNPACK #-} !ByteArray -> {-# UNPACK #-} !Maybe a -> !Radix1Tree a -> Radix1Tree a
+ Data.RadixTree.Word8.Strict.Unsafe: beyond :: Prefix -> Key -> Bool
+ Data.RadixTree.Word8.Strict.Unsafe: branchingBit :: Prefix -> Prefix -> Mask
+ Data.RadixTree.Word8.Strict.Unsafe: data MalformedTree
+ Data.RadixTree.Word8.Strict.Unsafe: data Radix1Tree a
+ Data.RadixTree.Word8.Strict.Unsafe: data RadixTree a
+ Data.RadixTree.Word8.Strict.Unsafe: lower :: Prefix -> Key
+ Data.RadixTree.Word8.Strict.Unsafe: mask :: Key -> Mask -> Prefix
+ Data.RadixTree.Word8.Strict.Unsafe: merge :: (Build -> a -> b -> Maybe c) -> (Build -> a -> Maybe c) -> (Build -> Radix1Tree a -> Radix1Tree c) -> (Build -> b -> Maybe c) -> (Build -> Radix1Tree b -> Radix1Tree c) -> RadixTree a -> RadixTree b -> RadixTree c
+ Data.RadixTree.Word8.Strict.Unsafe: type Key = Word8
+ Data.RadixTree.Word8.Strict.Unsafe: type Mask = Word8
+ Data.RadixTree.Word8.Strict.Unsafe: type Prefix = Word8
+ Data.RadixTree.Word8.Strict.Unsafe: upper :: Prefix -> Key
+ Data.RadixTree.Word8.Strict.Unsafe: zeroBit :: Key -> Mask -> Bool
+ Data.Zebra.Word: Black :: Color
+ Data.Zebra.Word: Equal :: PartialOrdering
+ Data.Zebra.Word: Incomparable :: PartialOrdering
+ Data.Zebra.Word: Subset :: PartialOrdering
+ Data.Zebra.Word: Superset :: PartialOrdering
+ Data.Zebra.Word: White :: Color
+ Data.Zebra.Word: compare :: Color -> Zebra -> Zebra -> PartialOrdering
+ Data.Zebra.Word: complement :: Zebra -> Zebra
+ Data.Zebra.Word: data Color
+ Data.Zebra.Word: data PartialOrdering
+ Data.Zebra.Word: data Range
+ Data.Zebra.Word: data Zebra
+ Data.Zebra.Word: difference :: Color -> Zebra -> Zebra -> Zebra
+ Data.Zebra.Word: disjoint :: Color -> Zebra -> Zebra -> Bool
+ Data.Zebra.Word: fillL :: Word -> Color -> Zebra -> Zebra
+ Data.Zebra.Word: fillR :: Word -> Color -> Zebra -> Zebra
+ Data.Zebra.Word: fillRange :: Range -> Color -> Zebra -> Zebra
+ Data.Zebra.Word: findL :: Word -> Color -> Word -> Zebra -> Word
+ Data.Zebra.Word: findR :: Word -> Color -> Word -> Zebra -> Word
+ Data.Zebra.Word: foldl :: (a -> Range -> Color -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldl' :: (a -> Range -> Color -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldlL :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldlL' :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldlR :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldlR' :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldlRange :: Range -> (a -> Range -> Color -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldlRange' :: Range -> (a -> Range -> Color -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldr :: (Range -> Color -> a -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldr' :: (Range -> Color -> a -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldrL :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldrL' :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldrR :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldrR' :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldrRange :: Range -> (Range -> Color -> a -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: foldrRange' :: Range -> (Range -> Color -> a -> a) -> a -> Zebra -> a
+ Data.Zebra.Word: intersection :: Color -> Zebra -> Zebra -> Zebra
+ Data.Zebra.Word: lookup :: Word -> Zebra -> Color
+ Data.Zebra.Word: lookupL :: Color -> Word -> Zebra -> Maybe Word
+ Data.Zebra.Word: lookupR :: Color -> Word -> Zebra -> Maybe Word
+ Data.Zebra.Word: monoL :: Word -> Zebra -> Maybe Color
+ Data.Zebra.Word: monoR :: Word -> Zebra -> Maybe Color
+ Data.Zebra.Word: monoRange :: Range -> Zebra -> Maybe Color
+ Data.Zebra.Word: pattern Mono :: Color -> Zebra
+ Data.Zebra.Word: pattern Range :: Word -> Word -> Range
+ Data.Zebra.Word: size :: Color -> Zebra -> Natural
+ Data.Zebra.Word: sizeL :: Color -> Word -> Zebra -> Natural
+ Data.Zebra.Word: sizeR :: Color -> Word -> Zebra -> Natural
+ Data.Zebra.Word: sizeRange :: Color -> Range -> Zebra -> Natural
+ Data.Zebra.Word: symmetricDifference :: Color -> Zebra -> Zebra -> Zebra
+ Data.Zebra.Word: union :: Color -> Zebra -> Zebra -> Zebra
+ Data.Zebra.Word.Debug: FoundNil :: Reason
+ Data.Zebra.Word.Debug: Invalid :: Reason -> Validity
+ Data.Zebra.Word.Debug: KeyBelow :: Prefix -> Key -> Reason
+ Data.Zebra.Word.Debug: NoSwitch :: Color -> Key -> Reason
+ Data.Zebra.Word.Debug: PrefixBelow :: Prefix -> Prefix -> Reason
+ Data.Zebra.Word.Debug: Valid :: Validity
+ Data.Zebra.Word.Debug: ZeroKey :: Reason
+ Data.Zebra.Word.Debug: ZeroPrefix :: Reason
+ Data.Zebra.Word.Debug: data Reason
+ Data.Zebra.Word.Debug: data Validity
+ Data.Zebra.Word.Debug: instance GHC.Show.Show Data.Zebra.Word.Debug.Reason
+ Data.Zebra.Word.Debug: instance GHC.Show.Show Data.Zebra.Word.Debug.Validity
+ Data.Zebra.Word.Debug: showsTree :: Zebra -> ShowS
+ Data.Zebra.Word.Debug: validate :: Zebra -> Validity
+ Data.Zebra.Word.Unsafe: Bin :: {-# UNPACK #-} !Prefix -> !Zebra -> !Zebra -> Zebra
+ Data.Zebra.Word.Unsafe: Bla :: {-# UNPACK #-} !Key -> Zebra
+ Data.Zebra.Word.Unsafe: Black :: Color
+ Data.Zebra.Word.Unsafe: Nil :: {-# UNPACK #-} !Color -> Zebra
+ Data.Zebra.Word.Unsafe: UnsafeRange :: {-# UNPACK #-} !Key -> {-# UNPACK #-} !Key -> Range
+ Data.Zebra.Word.Unsafe: Whi :: {-# UNPACK #-} !Key -> Zebra
+ Data.Zebra.Word.Unsafe: White :: Color
+ Data.Zebra.Word.Unsafe: beyond :: Prefix -> Key -> Bool
+ Data.Zebra.Word.Unsafe: branchingBit :: Prefix -> Prefix -> Mask
+ Data.Zebra.Word.Unsafe: data Color
+ Data.Zebra.Word.Unsafe: data Range
+ Data.Zebra.Word.Unsafe: data Zebra
+ Data.Zebra.Word.Unsafe: lower :: Prefix -> Key
+ Data.Zebra.Word.Unsafe: mask :: Key -> Mask -> Word
+ Data.Zebra.Word.Unsafe: pattern Mono :: Color -> Zebra
+ Data.Zebra.Word.Unsafe: pattern Range :: Word -> Word -> Range
+ Data.Zebra.Word.Unsafe: type Key = Word
+ Data.Zebra.Word.Unsafe: type Mask = Word
+ Data.Zebra.Word.Unsafe: type Prefix = Word
+ Data.Zebra.Word.Unsafe: unsafeFillL :: Word -> Color -> Zebra -> Zebra
+ Data.Zebra.Word.Unsafe: unsafeFillRange :: Word -> Word -> Color -> Zebra -> Zebra
+ Data.Zebra.Word.Unsafe: unsafeFoldlRange :: Word -> Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a
+ Data.Zebra.Word.Unsafe: unsafeFoldlRange' :: Word -> Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a
+ Data.Zebra.Word.Unsafe: unsafeFoldrRange :: Word -> Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a
+ Data.Zebra.Word.Unsafe: unsafeFoldrRange' :: Word -> Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a
+ Data.Zebra.Word.Unsafe: unsafeMonoRange :: Word -> Word -> Zebra -> Maybe Color
+ Data.Zebra.Word.Unsafe: unsafeSize :: Color -> Zebra -> Word
+ Data.Zebra.Word.Unsafe: unsafeSizeL :: Color -> Word -> Zebra -> Word
+ Data.Zebra.Word.Unsafe: unsafeSizeR :: Color -> Word -> Zebra -> Word
+ Data.Zebra.Word.Unsafe: unsafeSizeRange :: Color -> Word -> Word -> Zebra -> Word
+ Data.Zebra.Word.Unsafe: upper :: Prefix -> Key
+ Data.Zebra.Word.Unsafe: zeroBit :: Key -> Mask -> Bool

Files

− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
− bench/RadixTreeBench.hs
@@ -1,146 +0,0 @@-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE ScopedTypeVariables #-}--module Main (main) where--import Control.Arrow-import Control.DeepSeq-import Control.Exception--import Data.Foldable--import qualified Data.ByteString.Short as BSS-import qualified Data.HashMap.Strict as HM-import qualified Data.Map.Strict as M-import qualified Data.Text.Encoding as TE-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Lazy.IO as TLIO--import qualified Data.HashTable.IO as HT--import Gauge--import qualified Data.RadixTree.Internal as RT--main :: IO ()-main = do-  let config = defaultConfig-        { resamples   = 10000-        , displayMode = Condensed-        , rerunsLimit = 1-        }--  contents <- TLIO.readFile "/tmp/tags-ebac8dcc87fd1f1b1e7016d6585549309e3c5016-haskell-mode"-  let tags :: [TL.Text]-      tags = filter (not . TL.null) $ map (head . TL.splitOn "\t") $ drop 1 $ TL.lines contents--      decodeBS = TE.encodeUtf8 . TL.toStrict-      decode = BSS.toShort . decodeBS--      tags' :: [BSS.ShortByteString]-      tags' = map decode tags--      tags'' :: [(BSS.ShortByteString, ())]-      tags'' = map (id &&& const ()) tags'--      tagsRev'' :: [(BSS.ShortByteString, ())]-      tagsRev'' = map ((BSS.pack . reverse . BSS.unpack) &&& const ()) tags'--      -- tagsBS :: [(BS.ByteString, ())]-      -- tagsBS = map (decodeBS &&& const ()) tags--      queriesPresent :: [BSS.ShortByteString]-      queriesPresent = tags' ++ map (BSS.pack . reverse . BSS.unpack) tags'--      queriesMissing :: [BSS.ShortByteString]-      queriesMissing = map (BSS.pack . reverse . BSS.unpack) tags'--      queriesBoth :: [BSS.ShortByteString]-      queriesBoth = tags' ++ map (BSS.pack . reverse . BSS.unpack) tags'--  evaluate $ rnf tags'-  evaluate $ rnf tags''-  evaluate $ rnf tagsRev''-  evaluate $ rnf queriesPresent-  evaluate $ rnf queriesMissing-  evaluate $ rnf queriesBoth--  let radixTree    = RT.fromList tags''-      radixTreeRev = RT.fromList tagsRev''-      treeMap      = M.fromList  tags''-      treeMapRev   = M.fromList  tagsRev''-      hashMap      = HM.fromList tags''-      hashMapRev   = HM.fromList tagsRev''--  evaluate $ rnf radixTree-  evaluate $ rnf radixTreeRev-  evaluate $ rnf treeMap-  evaluate $ rnf treeMapRev-  evaluate $ rnf hashMap-  evaluate $ rnf hashMapRev--  (basic  :: HT.BasicHashTable  BSS.ShortByteString ()) <- HT.new-  -- (linear :: HT.LinearHashTable BSS.ShortByteString ()) <- HT.new-  (cuckoo :: HT.CuckooHashTable BSS.ShortByteString ()) <- HT.new-  for_ tags'' $ \(k, v) -> do-    HT.insert basic  k v-    -- HT.insert linear k v-    HT.insert cuckoo k v--  defaultMainWith config-    [ bgroup "creation"-      [ bench "Data.RadixTree"  $ nf RT.fromList tags''-      , bench "Data.Map"        $ nf M.fromList tags''-      , bench "Data.HashMap"    $ nf HM.fromList tags''-      , bench "BasicHashTable"  $ nfIO $ do-          (ht :: HT.BasicHashTable  BSS.ShortByteString ()) <- HT.new-          for_ tags'' $ \(k, v) -> HT.insert ht k v-      -- , bench "LinearHashTable"  $ nfIO $ do-      --     (ht :: HT.LinearHashTable BSS.ShortByteString ()) <- HT.new-      --     for_ tags'' $ \(k, v) -> HT.insert ht k v-      , bench "CuckooHashTable"  $ nfIO $ do-          (ht :: HT.CuckooHashTable BSS.ShortByteString ()) <- HT.new-          for_ tags'' $ \(k, v) -> HT.insert ht k v-      ]-    , bgroup "lookup"-        [ bgroup "present"-          [ bench "Data.RadixTree"  $ nf (map (`RT.lookup` radixTree)) queriesPresent-          , bench "Data.Map"        $ nf (map (`M.lookup`  treeMap))   queriesPresent-          , bench "Data.HashMap"    $ nf (map (`HM.lookup` hashMap))   queriesPresent-          , bench "BasicHashTable"  $ nfIO $ traverse (HT.lookup basic)  queriesPresent-          -- , bench "LinearHashTable" $ nfIO $ traverse (HT.lookup linear) queriesPresent-          , bench "CuckooHashTable" $ nfIO $ traverse (HT.lookup cuckoo) queriesPresent-          ]-        , bgroup "missing"-          [ bench "Data.RadixTree"  $ nf (map (`RT.lookup` radixTree)) queriesMissing-          , bench "Data.Map"        $ nf (map (`M.lookup`  treeMap))   queriesMissing-          , bench "Data.HashMap"    $ nf (map (`HM.lookup` hashMap))   queriesMissing-          , bench "BasicHashTable"  $ nfIO $ traverse (HT.lookup basic)  queriesMissing-          -- , bench "LinearHashTable" $ nfIO $ traverse (HT.lookup linear) queriesMissing-          , bench "CuckooHashTable" $ nfIO $ traverse (HT.lookup cuckoo) queriesMissing-          ]-        , bgroup "both"-          [ bench "Data.RadixTree"  $ nf (map (`RT.lookup` radixTree)) queriesBoth-          , bench "Data.Map"        $ nf (map (`M.lookup`  treeMap))   queriesBoth-          , bench "Data.HashMap"    $ nf (map (`HM.lookup` hashMap))   queriesBoth-          , bench "BasicHashTable"  $ nfIO $ traverse (HT.lookup basic)  queriesBoth-          -- , bench "LinearHashTable" $ nfIO $ traverse (HT.lookup linear) queriesBoth-          , bench "CuckooHashTable" $ nfIO $ traverse (HT.lookup cuckoo) queriesBoth-          ]-        ]-    , bgroup "keys"-      [ bench "Data.RadixTree" $ nf RT.keys radixTree-      , bench "Data.Map"       $ nf M.keys treeMap-      , bench "Data.HashMap"   $ nf HM.keys hashMap-      ]-    , bgroup "toList"-      [ bench "Data.RadixTree" $ nf RT.toList radixTree-      , bench "Data.Map"       $ nf M.toList treeMap-      , bench "Data.HashMap"   $ nf HM.toList hashMap-      ]-    , bgroup "union"-      [ bench "Data.RadixTree" $ nf (uncurry RT.union) (radixTree, radixTreeRev)-      , bench "Data.Map"       $ nf (uncurry M.union) (treeMap, treeMapRev)-      , bench "Data.HashMap"   $ nf (uncurry HM.union) (hashMap, hashMapRev)-      ]-    ]
+ no/No/Set/Word.hs view
@@ -0,0 +1,387 @@+{-# LANGUAGE DerivingStrategies+           , GeneralizedNewtypeDeriving+           , PatternSynonyms+           , ViewPatterns #-}++module No.Set.Word+  ( Color (..)+  , other++  , NoSet (Mono, ..)++  , No.Set.Word.lookup+  , lookupL+  , findL+  , lookupR+  , findR++  , Range (..)+  , monoL+  , monoR+  , monoRange++  , size+  , sizeL+  , sizeR+  , sizeRange++  , fillL+  , fillR+  , fillRange++  , No.Set.Word.foldl+  , No.Set.Word.foldl'+  , No.Set.Word.foldr+  , No.Set.Word.foldr'++  , foldlL+  , foldlL'+  , foldrL+  , foldrL'++  , foldlR+  , foldlR'+  , foldrR+  , foldrR'++  , foldlRange+  , foldlRange'+  , foldrRange+  , foldrRange'++  , complement++  , union+  , disjoint+  , intersection++  , difference+  , symmetricDifference++  , PartialOrdering (..)+  , No.Set.Word.compare+  ) where+++import           Data.Zebra.Word (Color (..), PartialOrdering (..))+import           Data.Zebra.Word.Unsafe (Range (..))++import           Data.Foldable+import           Data.Sequence (Seq (..))+import qualified Data.Sequence as Seq+import           Numeric.Natural++++other :: Color -> Color+other Black = White+other White = Black++++newtype NoSet = NoSet { getNoSet :: Seq (Color, Word, Word) }+                deriving newtype Eq++instance Show NoSet where+  showsPrec _ (NoSet xs) =+    showList . fmap (\(_, kL, kR) -> (kL, kR))+             . filter (\(c, _, _) -> c == White)+             $ toList xs++pattern Mono :: Color -> NoSet+pattern Mono c <- (monotone -> Just c)+  where+    Mono c = NoSet $ Seq.singleton (c, 0, maxBound)++monotone :: NoSet -> Maybe Color+monotone (NoSet (Seq.Empty Seq.:|> (c, _, _))) = Just c+monotone _                                     = Nothing++++lookup :: Word -> NoSet -> Color+lookup w no =+  let ~(NoSet l, _) = unsafeSplitL w no+  in case l of+       _ :|> (c, _, _) -> c+       Empty           ->+         error $ "No.Set.Word.lookup: out of bounds (" <> shows w ")"++++lookupL :: Color -> Word -> NoSet -> Maybe Word+lookupL x w no =+  let ~(NoSet l, _) = unsafeSplitL w no+  in case l of+       _ :|> _ -> go l+       Empty   ->+         error $ "No.Set.Word.lookupL: out of bounds (" <> shows w ")"++  where+    go (l :|> (c, _, b)) | c == x    = Just b+                         | otherwise = go l+    go Empty = Nothing++findL :: Word -> Color -> Word -> NoSet -> Word+findL d x w no =+  case lookupL x w no of+    Just a  -> a+    Nothing -> d++++lookupR :: Color -> Word -> NoSet -> Maybe Word+lookupR x w no =+  let ~(_, NoSet r) = unsafeSplitR w no+  in case r of+       _ :<| _ -> go r+       Empty   ->+         error $ "No.Set.Word.lookupR: out of bounds (" <> shows w ")"++  where+    go ((c, a, _) :<| r) | c == x    = Just a+                         | otherwise = go r+    go Empty = Nothing++findR :: Word -> Color -> Word -> NoSet -> Word+findR d x w no =+  case lookupR x w no of+    Just a  -> a+    Nothing -> d++++monoL :: Word -> NoSet -> Maybe Color+monoL k = monotone . fst . unsafeSplitL k++monoR :: Word -> NoSet -> Maybe Color+monoR k = monotone . snd . unsafeSplitR k++monoRange :: Range -> NoSet -> Maybe Color+monoRange r = monotone . (\(_, m, _) -> m) . unsafeSplitRange r++++size :: Color -> NoSet -> Natural+size x =+  let f (c, a, b) z+        | c == x    = fromIntegral (b - a) + 1 + z+        | otherwise = z++  in Data.Foldable.foldr f 0 . getNoSet++sizeL :: Color -> Word -> NoSet -> Natural+sizeL x k = size x . fst . unsafeSplitL k++sizeR :: Color -> Word -> NoSet -> Natural+sizeR x k = size x . snd . unsafeSplitR k++sizeRange :: Color -> Range -> NoSet -> Natural+sizeRange x r = size x . (\(_, m, _) -> m) . unsafeSplitRange r++++fillL :: Word -> Color -> NoSet -> NoSet+fillL w x no =+  let ~(_, NoSet _r) = unsafeSplitL w no+  in case _r of+       (c, _, b) :<| r | c == x    -> NoSet $ (c, 0, b) :<| r+                       | otherwise -> NoSet $ (x, 0, w) :<| _r++       _                           -> Mono x++fillR :: Word -> Color -> NoSet -> NoSet+fillR w x no =+  let ~(NoSet _l, _) = unsafeSplitR w no+  in case _l of+       l :|> (c, a, _) | c == x    -> NoSet $ l :|> (c, a, maxBound)+                       | otherwise -> NoSet $ _l :|> (x, w, maxBound)++       _                           -> Mono x++fillRange :: Range -> Color -> NoSet -> NoSet+fillRange rng@(Range kL kR) x no =+  let ~(NoSet _l, _, NoSet _r) = unsafeSplitRange rng no+  in case (_l, _r) of+       (l :|> (cL, a, _), (cR, _, b) :<| r) ->+         case (cL == cR, cL == x) of+           (True , True ) -> NoSet $ l <> ((x, a, b) :<| r)+           (True , False) -> NoSet $ _l <> ((x, kL, kR) :<| _r)+           (False, True ) -> NoSet $ (l :|> (x, a, kR)) <> _r+           (False, False) -> NoSet $ _l <> ((x, a, b) :<| r)++       (l :|> (cL, a, _), Empty)+         | cL == x   -> NoSet $ l :|> (cL, a, maxBound)+         | otherwise -> NoSet $ _l :|> (x, kL, maxBound)++       (Empty, (cR, _, b) :<| r)+         | cR == x   -> NoSet $ (cR, 0, b) :<| r+         | otherwise -> NoSet $ (x, 0, kR) :<| _r++       (Empty, Empty) -> Mono x++++unsafeSplitL :: Word -> NoSet -> (NoSet, NoSet)+unsafeSplitL k (NoSet xs) =+  let ~(_l, r) = Seq.spanl (\(_, a, _) -> a <= k) xs+  in case _l of+       l :|> (c, a, b) | b > k -> (NoSet $ l :|> (c, a, k), NoSet $ (c, k + 1, b) :<| r)+       _                       -> (NoSet _l, NoSet r)++unsafeSplitR :: Word -> NoSet -> (NoSet, NoSet)+unsafeSplitR k (NoSet xs) =+  let ~(_r, l) = Seq.spanr (\(_, _, b) -> b >= k) xs+  in case _r of+      (c, a, b) :<| r | a < k -> (NoSet $ l :|> (c, a, k - 1), NoSet $ (c, k, b) :<| r)+      _                       -> (NoSet l, NoSet _r)++unsafeSplitRange :: Range -> NoSet -> (NoSet, NoSet, NoSet)+unsafeSplitRange (Range kL kR) no =+  let ~(l, no') = unsafeSplitR kL no+      ~(m, r)   = unsafeSplitL kR no'+  in (l, m, r)++++foldl, foldl' :: (a -> Range -> Color -> a) -> a -> NoSet -> a+foldl  f z0 = Data.Foldable.foldl  (\z (c, a, b) -> f z (UnsafeRange a b) c) z0 . getNoSet+foldl' f z0 = Data.Foldable.foldl' (\z (c, a, b) -> f z (UnsafeRange a b) c) z0 . getNoSet++foldr, foldr' :: (Range -> Color -> a -> a) -> a -> NoSet -> a+foldr  f z0 = Data.Foldable.foldr  (\(c, a, b) -> f (UnsafeRange a b) c) z0 . getNoSet+foldr' f z0 = Data.Foldable.foldr' (\(c, a, b) -> f (UnsafeRange a b) c) z0 . getNoSet++++foldlL, foldlL' :: Word -> (a -> Range -> Color -> a) -> a -> NoSet -> a+foldlL  w f z = No.Set.Word.foldl  f z . fst . unsafeSplitL w+foldlL' w f z = No.Set.Word.foldl' f z . fst . unsafeSplitL w++foldrL, foldrL' :: Word -> (Range -> Color -> a -> a) -> a -> NoSet -> a+foldrL  w f z = No.Set.Word.foldr  f z . fst . unsafeSplitL w+foldrL' w f z = No.Set.Word.foldr' f z . fst . unsafeSplitL w++++foldlR, foldlR' :: Word -> (a -> Range -> Color -> a) -> a -> NoSet -> a+foldlR  w f z = No.Set.Word.foldl  f z . snd . unsafeSplitR w+foldlR' w f z = No.Set.Word.foldl' f z . snd . unsafeSplitR w++foldrR, foldrR' :: Word -> (Range -> Color -> a -> a) -> a -> NoSet -> a+foldrR  w f z = No.Set.Word.foldr  f z . snd . unsafeSplitR w+foldrR' w f z = No.Set.Word.foldr' f z . snd . unsafeSplitR w++++foldlRange, foldlRange' :: Range -> (a -> Range -> Color -> a) -> a -> NoSet -> a+foldlRange  r f z = No.Set.Word.foldl  f z . (\(_, m, _) -> m) . unsafeSplitRange r+foldlRange' r f z = No.Set.Word.foldl' f z . (\(_, m, _) -> m) . unsafeSplitRange r++foldrRange, foldrRange' :: Range -> (Range -> Color -> a -> a) -> a -> NoSet -> a+foldrRange  r f z = No.Set.Word.foldr  f z . (\(_, m, _) -> m) . unsafeSplitRange r+foldrRange' r f z = No.Set.Word.foldr' f z . (\(_, m, _) -> m) . unsafeSplitRange r++++-- | Combines two sets into an ascending non-overlapping list of+--   consecutive double-colored ranges.+--+--   Both sets must be defined over the same ranges for this function to make sense.+crush :: NoSet -> NoSet -> [(Color, Range, Color)]+crush (NoSet xs) (NoSet ys) = go xs ys+  where+    go Empty                Empty                = []+    go ((cL, aL, bL) :<| l) ((cR, aR, bR) :<| r) =+      case bL `Prelude.compare` bR of+        LT -> (cL, UnsafeRange aL bL, cR) : go l ((cR, bL + 1, bR) :<| r)+        GT -> (cL, UnsafeRange aR bR, cR) : go ((cL, bR + 1, bL) :<| l) r+        EQ -> (cL, UnsafeRange aL bL, cR) : go l r++    go _ _ =+      error "No.Set.Word.crush: unequally sized sets"++++complement :: NoSet -> NoSet+complement = NoSet . fmap (\(c, a, b) -> (other c, a, b)) . getNoSet++++union :: Color -> NoSet -> NoSet -> NoSet+union x =+  merge $ \cL cR ->+    if cL == cR && cL /= x+      then cL+      else x++disjoint :: Color -> NoSet -> NoSet -> Bool+disjoint x a b =+  case intersection x a b of+    Mono y -> x /= y+    _      -> False++intersection :: Color -> NoSet -> NoSet -> NoSet+intersection x =+  merge $ \cL cR ->+    if cL == cR && cL == x+      then x+      else other x++difference :: Color -> NoSet -> NoSet -> NoSet+difference x =+  merge $ \cL cR ->+    if cL /= cR && cL == x+      then x+      else other x++symmetricDifference :: Color -> NoSet -> NoSet -> NoSet+symmetricDifference x =+  merge $ \cL cR ->+    if cL == cR+      then other x+      else x+++++data Carry = Carry Color Word+           | NoCarry++merge :: (Color -> Color -> Color) -> NoSet -> NoSet -> NoSet+merge f as bs = NoSet . Seq.fromList . unify NoCarry $ crush as bs+  where+    unify carry [] =+      case carry of+        NoCarry   -> []+        Carry c k -> (c, k, maxBound) : []++    unify carry ((cL, Range a _, cR) : rest) =+      let cM = f cL cR+      in case carry of+           NoCarry   -> unify (Carry cM a) rest+           Carry c k+             | c == cM   -> unify carry rest+             | otherwise -> (c, k, a - 1) : unify (Carry cM a) rest++++compare :: Color -> NoSet -> NoSet -> PartialOrdering+compare x as bs = Data.Foldable.foldr go Equal $ crush as bs+  where+    go (cL, _, cR) p =+      case p of+        Subset+          | cL == cR || cR == x -> Subset+          | otherwise           -> Incomparable++        Superset+          | cL == cR || cL == x -> Superset+          | otherwise           -> Incomparable++        Equal+          | cL == cR  -> Equal+          | cR == x   -> Subset+          | otherwise -> Superset++        Incomparable -> Incomparable
+ no/No/Tree.hs view
@@ -0,0 +1,632 @@+{-# LANGUAGE DerivingStrategies+           , GeneralizedNewtypeDeriving+           , PatternSynonyms #-}++module No.Tree+  ( NoTree+  , empty+  , singleton++  , No.Tree.null++  , fromList+  , No.Tree.toList++  , No.Tree.map+  , mapWithKey++  , size+  , No.Tree.foldl+  , foldlWithKey+  , No.Tree.foldr+  , foldrWithKey+  , No.Tree.foldMap+  , foldMapWithKey++  , No.Tree.traverse+  , traverseWithKey++  , No.Tree.lookup+  , find+  , member++  , prefix+  , subtree++  , insert+  , insertWith+  , adjust+  , delete+  , update+  , alter++  , prune+  , shape++  , Openness (..)+  , lookupL+  , adjustL+  , adjustLWithKey+  , deleteL+  , updateL+  , updateLWithKey+  , takeL++  , lookupR+  , adjustR+  , adjustRWithKey+  , deleteR+  , updateR+  , updateRWithKey+  , takeR++  , Range (WordRange, StringRange, ..)+  , adjustRange+  , adjustRangeWithKey+  , deleteRange+  , updateRange+  , updateRangeWithKey+  , takeRange++  , unionL+  , unionWithKey++  , difference+  , differenceWithKey++  , intersectionL+  , intersectionWithKey++  , No.Tree.compare++  , splitL+  , splitR+  , splitLookup++  , No.Tree.filter+  , filterWithKey++  , No.Tree.mapMaybe+  , mapMaybeWithKey++  , partition+  , partitionWithKey++  , mapEither+  , mapEitherWithKey++  , lookupMin+  , lookupMinWithKey+  , lookupMax+  , lookupMaxWithKey++  , adjustMin+  , adjustMinWithKey+  , adjustMax+  , adjustMaxWithKey++  , deleteMin+  , deleteMax++  , updateMin+  , updateMinWithKey+  , updateMax+  , updateMaxWithKey++  , minView+  , maxView+  ) where++import           Data.Patricia.Word.Strict (PartialOrdering (..))+import           Data.RadixTree.Word8.Strict (Openness (..))++import           Data.Sequence (Seq (..))+import qualified Data.Sequence as Seq+import           Data.Maybe+import           Data.Either+import           Data.Foldable (toList)+import qualified Data.List as List+import           Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NonEmpty++++newtype NoTree k a = NoTree { getNoTree :: Seq (k, a) }+                     deriving newtype (Show, Eq)++empty :: NoTree k a+empty = NoTree Seq.empty++singleton :: k -> a -> NoTree k a+singleton k a = NoTree $ Seq.singleton (k, a)+++null :: NoTree k a -> Bool+null = Seq.null . getNoTree++++fromList :: Ord k => [(k, a)] -> NoTree k a+fromList = NoTree . Seq.fromList . List.nubBy (\(k, _) (l, _) -> k == l) . List.sortOn fst++toList :: NoTree k a -> [(k, a)]+toList (NoTree as) = Data.Foldable.toList as++++map :: (a -> b) -> NoTree k a -> NoTree k b+map f = mapWithKey (\_ -> f)++mapWithKey :: (k -> a -> b) -> NoTree k a -> NoTree k b+mapWithKey f (NoTree as) = NoTree $ fmap (\(ks, a) -> (ks, f ks a)) as+++size :: NoTree k a -> Int+size = No.Tree.foldr (\_ -> (+) 1) 0++foldl :: (b -> a -> b) -> b -> NoTree k a -> b+foldl f = foldlWithKey (\z _ -> f z)++foldlWithKey :: (b -> k -> a -> b) -> b -> NoTree k a -> b+foldlWithKey f z (NoTree as) = Prelude.foldl (\z' (ks, a) -> f z' ks a) z as++foldr :: (a -> b -> b) -> b -> NoTree k a -> b+foldr f = foldrWithKey (\_ -> f)++foldrWithKey :: (k -> a -> b -> b) -> b -> NoTree k a -> b+foldrWithKey f z (NoTree as) = Prelude.foldr (\(ks, a) -> f ks a) z as++foldMap :: Monoid m => (a -> m) -> NoTree k a -> m+foldMap f = foldMapWithKey (\_ -> f)++foldMapWithKey :: Monoid m => (k -> a -> m) -> NoTree k a -> m+foldMapWithKey f (NoTree as) = Prelude.foldMap (\(ks, a) -> f ks a) as++traverse :: Applicative f => (a -> f b) -> NoTree k a -> f (NoTree k b)+traverse f = traverseWithKey (\_ -> f)++traverseWithKey+  :: Applicative f => (k -> a -> f b) -> NoTree k a -> f (NoTree k b)+traverseWithKey f (NoTree as) =+  NoTree <$> Prelude.traverse (\(ks, a) -> (,) ks <$> f ks a) as++++lookup :: Ord k => k -> NoTree k a -> Maybe a+lookup k = (\(_, mx, _) -> mx) <$> splitLookup k++find :: Ord k => a -> k -> NoTree k a -> a+find d k = (\(_, mx, _) -> fromMaybe d mx) <$> splitLookup k++member :: Ord k => k -> NoTree k a -> Bool+member k = (\(_, mx, _) -> maybe False (\_ -> True) mx) <$> splitLookup k++++subtree :: Ord k => [k] -> NoTree [k] a -> NoTree [k] a+subtree ks (NoTree as) =+  let (_, bs) = Seq.spanl (\(w, _) -> not $ List.isPrefixOf ks w) as+      (cs, _) = Seq.spanl (\(w, _) ->       List.isPrefixOf ks w) bs++  in NoTree $ fmap (\(k, a) -> (drop (length ks) k, a)) cs++prefix :: [k] -> NoTree [k] a -> NoTree [k] a+prefix k (NoTree as) = NoTree $ fmap (\(w, a) -> (k <> w, a)) as++++insert :: Ord k => k -> a -> NoTree k a -> NoTree k a+insert k a = alter (\_ -> Just a) k++insertWith :: Ord k => (a -> a) -> k -> a -> NoTree k a -> NoTree k a+insertWith f k a = alter (Just . maybe a f) k++adjust :: Ord k => (a -> a) -> k -> NoTree k a -> NoTree k a+adjust f = alter (fmap f)++delete :: Ord k => k -> NoTree k a -> NoTree k a+delete k = alter (\_ -> Nothing) k++update :: Ord k => (a -> Maybe a) -> k -> NoTree k a -> NoTree k a+update f k = alter (f =<<) k++alter :: Ord k => (Maybe a -> Maybe a) -> k -> NoTree k a -> NoTree k a+alter f k no =+  let ~(NoTree as, mx, NoTree bs) = splitLookup k no+  in case f mx of+       Just y  -> NoTree $ as <> ((k, y) :<| bs)+       Nothing -> NoTree $ as <> bs++++prune :: Ord k => Openness -> [k] -> NoTree [k] a -> NoTree [k] a+prune o ks xs =+  let (NoTree ls, NoTree ms, NoTree rs) = breakOnPrefix ks xs++  in NoTree $ ls <> case ms of+                      (x, y) :<| _ | x == ks, Open <- o -> (x, y) :<| rs+                      _                                 -> rs++shape :: Ord k => (NoTree [k] a -> NoTree [k] a) -> [k] -> NoTree [k] a -> NoTree [k] a+shape f ks xs =+  let (NoTree ls, NoTree ms, NoTree rs) = breakOnPrefix ks xs++      NoTree ms' = f . NoTree $ fmap (\(k, a) -> (drop (length ks) k, a)) ms++  in NoTree $ ls <> fmap (\(k, a) -> (ks <> k, a)) ms' <> rs++breakOnPrefix :: Ord k => [k] -> NoTree [k] a -> (NoTree [k] a, NoTree [k] a, NoTree [k] a)+breakOnPrefix ks (NoTree xs) =+  let ~(as, bs) = Seq.spanl (\(ws, _) -> take (length ks) ws < ks) xs+      ~(cs, ds) = Seq.spanl (\(ws, _) -> List.isPrefixOf ks ws) bs++  in (NoTree as, NoTree cs, NoTree ds)++++lookupL :: Ord k => Openness -> k -> NoTree k a -> Maybe (k, a)+lookupL o k no =+  let NoTree as = takeL o k no+  in case as of+       _ :|> ka  -> Just ka+       Seq.Empty -> Nothing++adjustL :: Ord k => (a -> a) -> Openness -> k -> NoTree k a -> NoTree k a+adjustL f = shapeL (No.Tree.map f)++adjustLWithKey :: Ord k => (k -> a -> a) -> Openness -> k -> NoTree k a -> NoTree k a+adjustLWithKey f = shapeL (mapWithKey f)++deleteL :: Ord k => Openness -> k -> NoTree k a -> NoTree k a+deleteL = shapeL (\_ -> empty)++updateL :: Ord k => (a -> Maybe a) -> Openness -> k -> NoTree k a -> NoTree k a+updateL f = shapeL (No.Tree.mapMaybe f)++updateLWithKey :: Ord k => (k -> a -> Maybe a) -> Openness -> k -> NoTree k a -> NoTree k a+updateLWithKey f = shapeL (mapMaybeWithKey f)++takeL :: Ord k => Openness -> k -> NoTree k a -> NoTree k a+takeL Closed = deleteR Open+takeL Open   = deleteR Closed++shapeL :: Ord k => (NoTree k a -> NoTree k a) -> Openness -> k -> NoTree k a -> NoTree k a+shapeL f o k no =+  let ~(NoTree as, mx, NoTree bs) = splitLookup k no+  in case mx of+       Nothing -> NoTree $ getNoTree (f $ NoTree as) <> bs+       Just x  ->+         case o of+           Closed -> NoTree $ getNoTree (f $ NoTree (as :|> (k, x))) <> bs+           Open   -> NoTree $ getNoTree (f $ NoTree as) <> ((k, x) :<| bs)++++lookupR :: Ord k => Openness -> k -> NoTree k a -> Maybe (k, a)+lookupR o k no =+  let NoTree as = takeR o k no+  in case as of+       ka :<| _  -> Just ka+       Seq.Empty -> Nothing++adjustR :: Ord k => (a -> a) -> Openness -> k -> NoTree k a -> NoTree k a+adjustR f = shapeR (No.Tree.map f)++adjustRWithKey :: Ord k => (k -> a -> a) -> Openness -> k -> NoTree k a -> NoTree k a+adjustRWithKey f = shapeR (mapWithKey f)++deleteR :: Ord k => Openness -> k -> NoTree k a -> NoTree k a+deleteR = shapeR (\_ -> empty)++updateR :: Ord k => (a -> Maybe a) -> Openness -> k -> NoTree k a -> NoTree k a+updateR f = shapeR (No.Tree.mapMaybe f)++updateRWithKey :: Ord k => (k -> a -> Maybe a) -> Openness -> k -> NoTree k a -> NoTree k a+updateRWithKey f = shapeR (mapMaybeWithKey f)++takeR :: Ord k => Openness -> k -> NoTree k a -> NoTree k a+takeR Closed = deleteL Open+takeR Open   = deleteL Closed++shapeR :: Ord k => (NoTree k a -> NoTree k a) -> Openness -> k -> NoTree k a -> NoTree k a+shapeR f o k no =+  let ~(NoTree as, mx, NoTree bs) = splitLookup k no+  in case mx of+       Nothing -> NoTree $ as <> getNoTree (f $ NoTree bs)+       Just x  ->+         case o of+           Closed -> NoTree $ as <> getNoTree (f . NoTree $ (k, x) :<| bs)+           Open   -> NoTree $ (as :|> (k, x)) <> getNoTree (f $ NoTree bs)++++data Range k = UnsafeRange+                 {-# UNPACK #-} !Openness+                 k+                 {-# UNPACK #-} !Openness+                 k++instance Show k => Show (Range k) where+  showsPrec d (UnsafeRange oL kL oR kR) =+    showParen (d > 10) $+      showString "Range " . shows oL+              . showChar ' ' . shows kL+              . showChar ' ' . shows oR+              . showChar ' ' . shows kR++pattern WordRange+  :: (Bounded k, Num k, Ord k)+  => Openness+  -> k+  -> Openness+  -> k+  -> Range k+pattern WordRange oL kL oR kR <- UnsafeRange oL kL oR kR+  where+    WordRange o1 k1 o2 k2 =+      case Prelude.compare k1 k2 of+        LT -> UnsafeRange o1 k1 o2 k2+        GT -> UnsafeRange o2 k2 o1 k1+        EQ ->+          let o | Closed <- o1, Closed <- o2 = Closed+                | otherwise                  = Open++          in if k1 == maxBound+               then UnsafeRange Open (maxBound - 1) o maxBound+               else UnsafeRange o k1 Open (k1 + 1)++pattern StringRange+  :: (Bounded k, Ord k, Num k)+  => Openness+  -> NonEmpty k+  -> Openness+  -> NonEmpty k+  -> Range (NonEmpty k)+pattern StringRange oL kL oR kR <- UnsafeRange oL kL oR kR+  where+    StringRange o1 k1 o2 k2 =+      case Prelude.compare k1 k2 of+        LT -> UnsafeRange o1 k1 o2 k2+        GT -> UnsafeRange o2 k2 o1 k1+        EQ ->+          let o | Closed <- o1, Closed <- o2 = Closed+                | otherwise                  = Open++              x = NonEmpty.last k1+              xs = NonEmpty.init k1++          in if x == maxBound+               then UnsafeRange Open (NonEmpty.fromList $ xs <> [x - 1]) o k1+               else UnsafeRange o k1 Open (NonEmpty.fromList $ xs <> [x + 1])++++adjustRange :: Ord k => (a -> a) -> Range k -> NoTree k a -> NoTree k a+adjustRange f = shapeRange (No.Tree.map f)++adjustRangeWithKey :: Ord k => (k -> a -> a) -> Range k -> NoTree k a -> NoTree k a+adjustRangeWithKey f = shapeRange (mapWithKey f)++deleteRange :: Ord k => Range k -> NoTree k a -> NoTree k a+deleteRange = shapeRange (\_ -> empty)++updateRange :: Ord k => (a -> Maybe a) -> Range k -> NoTree k a -> NoTree k a+updateRange f = shapeRange (No.Tree.mapMaybe f)++updateRangeWithKey :: Ord k => (k -> a -> Maybe a) -> Range k -> NoTree k a -> NoTree k a+updateRangeWithKey f = shapeRange (mapMaybeWithKey f)++takeRange :: Ord k => Range k -> NoTree k a -> NoTree k a+takeRange (UnsafeRange oL kL oR kR) = takeR oL kL . takeL oR kR++shapeRange :: Ord k => (NoTree k a -> NoTree k a) -> Range k -> NoTree k a -> NoTree k a+shapeRange f (UnsafeRange oL kL oR kR) = shapeR (shapeL f oR kR) oL kL++++merge+  :: Ord k+  => (k -> a -> b -> Maybe c)+  -> (a -> Maybe c)+  -> (b -> Maybe c)+  -> NoTree k a+  -> NoTree k b+  -> NoTree k c+merge f l r (NoTree as) (NoTree bs) =+  NoTree . Seq.fromList $ go (Data.Foldable.toList as) (Data.Foldable.toList bs)+  where+    go ((ks, x) : xs) ((ls, y) : ys) =+      case Prelude.compare ks ls of+        LT -> let rest = go xs ((ls, y) : ys)+              in case l x of+                   Just z  -> (ks, z) : rest+                   Nothing -> rest++        EQ -> let rest = go xs ys+              in case f ks x y of+                   Just z  -> (ks, z) : rest+                   Nothing -> rest++        GT -> let rest = go ((ks, x) : xs) ys+              in case r y of+                   Just z  -> (ls, z) : rest+                   Nothing -> rest++    go xs [] = Data.Maybe.mapMaybe (\(ks, x) -> (,) ks <$> l x) xs+    go [] ys = Data.Maybe.mapMaybe (\(ls, y) -> (,) ls <$> r y) ys++++unionL :: Ord k => NoTree k a -> NoTree k a -> NoTree k a+unionL = unionWithKey (\_ a _ -> a)++unionWithKey+  :: Ord k => (k -> a -> a -> a) -> NoTree k a -> NoTree k a -> NoTree k a+unionWithKey f = merge (\ks a b -> Just $ f ks a b) Just Just+++difference :: Ord k => NoTree k a -> NoTree k b -> NoTree k a+difference = differenceWithKey (\_ _ _ -> Nothing)++differenceWithKey+  :: Ord k => (k -> a -> b -> Maybe a) -> NoTree k a -> NoTree k b -> NoTree k a+differenceWithKey f = merge f Just (\_ -> Nothing)+++intersectionL :: Ord k => NoTree k a -> NoTree k b -> NoTree k a+intersectionL = intersectionWithKey (\_ a _ -> a)++intersectionWithKey+  :: Ord k => (k -> a -> b -> c) -> NoTree k a -> NoTree k b -> NoTree k c+intersectionWithKey f =+  merge (\k a b -> Just $ f k a b) (\_ -> Nothing) (\_ -> Nothing)++++compare :: (Eq a, Ord k) => NoTree k a -> NoTree k a -> PartialOrdering+compare xs@(NoTree as) ys@(NoTree bs)+  | as == bs                                   = Equal++  | NoTree is <- intersectionL xs ys, is == as+  , NoTree us <- unionL        xs ys, us == bs = Subset++  | NoTree is <- intersectionL xs ys, is == bs+  , NoTree us <- unionL        xs ys, us == as = Superset++  | otherwise                                  = Incomparable++++splitL :: Ord k => Openness -> k -> NoTree k a -> (NoTree k a, NoTree k a)+splitL o k t =+  let (NoTree l, mx, NoTree r) = splitLookup k t+  in case mx of+       Just x  -> case o of+                    Closed -> (NoTree $ l :|> (k, x), NoTree r)+                    Open   -> (NoTree $ l, NoTree $ (k, x) :<| r)++       Nothing -> (NoTree l, NoTree r)++splitR :: Ord k => k -> NoTree k a -> (NoTree k a, NoTree k a)+splitR k t =+  let (l, mx, NoTree r) = splitLookup k t+  in ( l+     , NoTree $ case mx of+                  Just x  -> (k, x) :<| r+                  Nothing -> r+     )++splitLookup :: Ord k => k -> NoTree k a -> (NoTree k a, Maybe a, NoTree k a)+splitLookup ws (NoTree as) =+  let (before, after) = Seq.spanl (\(ks, _) -> ks < ws) as+  in case after of+       (cs, a) :<| rest | cs == ws -> (NoTree before, Just a , NoTree rest)+       _                           -> (NoTree before, Nothing, NoTree after)++++filter :: (a -> Bool) -> NoTree k a -> NoTree k a+filter f = fst . partition f++filterWithKey :: (k -> a -> Bool) -> NoTree k a -> NoTree k a+filterWithKey f = fst . partitionWithKey f++mapMaybe :: (a -> Maybe b) -> NoTree k a -> NoTree k b+mapMaybe f = fst . mapEitherWithKey (\_ -> maybe (Right ()) Left . f)++mapMaybeWithKey :: (k -> a -> Maybe b) -> NoTree k a -> NoTree k b+mapMaybeWithKey f = fst . mapEitherWithKey (\ks -> maybe (Right ()) Left . f ks)++partition :: (a -> Bool) -> NoTree k a -> (NoTree k a, NoTree k a)+partition f = mapEitherWithKey (\_ a -> if f a then Left a else Right a)++partitionWithKey :: (k -> a -> Bool) -> NoTree k a -> (NoTree k a, NoTree k a)+partitionWithKey f = mapEitherWithKey (\ks a -> if f ks a then Left a else Right a)++mapEither :: (a -> Either b c) -> NoTree k a -> (NoTree k b, NoTree k c)+mapEither f = mapEitherWithKey (\_ -> f)++mapEitherWithKey+  :: (k -> a -> Either b c) -> NoTree k a -> (NoTree k b, NoTree k c)+mapEitherWithKey f (NoTree as) =+  let ~(bs, cs) = partitionEithers $+                    flip fmap (Data.Foldable.toList as) $ \(ks, a) ->+                      case f ks a of+                        Left b  -> Left (ks, b)+                        Right c -> Right (ks, c)++  in (NoTree $ Seq.fromList bs, NoTree $ Seq.fromList cs)++++lookupMin :: NoTree k a -> Maybe a+lookupMin t = (\ (_, a, _) -> a) <$> minView t++lookupMinWithKey :: NoTree k a -> Maybe (k, a)+lookupMinWithKey t = (\ (k, a, _) -> (k, a)) <$> minView t++deleteMin :: NoTree k a -> NoTree k a+deleteMin = updateMin (\_ -> Nothing)++adjustMin :: (a -> a) -> NoTree k a -> NoTree k a+adjustMin f = adjustMinWithKey (\_ -> f)++adjustMinWithKey :: (k -> a -> a) -> NoTree k a -> NoTree k a+adjustMinWithKey f = updateMinWithKey (\k a -> Just $ f k a)++updateMin :: (a -> Maybe a) -> NoTree k a -> NoTree k a+updateMin f = updateMinWithKey (\_ -> f)++updateMinWithKey :: (k -> a -> Maybe a) -> NoTree k a -> NoTree k a+updateMinWithKey f (NoTree as) =+  NoTree $+    case as of+      (k, a) :<| bs ->+        case f k a of+          Just b  -> (k, b) :<| bs+          Nothing -> bs++      Empty         -> Seq.empty++minView :: NoTree k a -> Maybe (k, a, NoTree k a)+minView (NoTree as) =+  case as of+    (k, a) :<| bs -> Just (k, a, NoTree bs)+    Empty         -> Nothing++++lookupMax :: NoTree k a -> Maybe a+lookupMax t = (\ (_, _, a) -> a) <$> maxView t++lookupMaxWithKey :: NoTree k a -> Maybe (k, a)+lookupMaxWithKey t = (\ (_, k, a) -> (k, a)) <$> maxView t++deleteMax :: NoTree k a -> NoTree k a+deleteMax = updateMax (\_ -> Nothing)++adjustMax :: (a -> a) -> NoTree k a -> NoTree k a+adjustMax f = adjustMaxWithKey (\_ -> f)++adjustMaxWithKey :: (k -> a -> a) -> NoTree k a -> NoTree k a+adjustMaxWithKey f = updateMaxWithKey (\k a -> Just $ f k a)++updateMax :: (a -> Maybe a) -> NoTree k a -> NoTree k a+updateMax f = updateMaxWithKey (\_ -> f)++updateMaxWithKey :: (k -> a -> Maybe a) -> NoTree k a -> NoTree k a+updateMaxWithKey f (NoTree as) =+  NoTree $+    case as of+      bs :|> (k, a) ->+        case f k a of+          Just b  -> bs :|> (k, b)+          Nothing -> bs++      Empty         -> Seq.empty++maxView :: NoTree k a -> Maybe (NoTree k a, k, a)+maxView (NoTree as) =+  case as of+    bs :|> (k, a) -> Just (NoTree bs, k, a)+    Empty         -> Nothing
radix-tree.cabal view
@@ -1,143 +1,144 @@-name:-  radix-tree-version:-  0.1-category:-  Data Structures-synopsis:-  Radix tree data structive over short byte-strings-description:-  This module provides a memory-efficient map from-  Data.ByteString.Short keys to arbitrary values implemented as a radix-  tree datastructure. Memory efficiency is achieved by sharing common-  prefixes of all keys.-license:-  BSD3-license-file:-  LICENSE-author:-  Sergey Vinokurov-maintainer:-  Sergey Vinokurov <serg.foo@gmail.com>-copyright:-  (c) 2018 Sergey Vinokurov-tested-with:-  GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3+name:          radix-tree+version:       1.0.0.0 -cabal-version:-  2.0-build-type:-  Simple+category:      Data Structures+synopsis:      Radix trees.+description:   Radix and PATRICIA trees, both spine-strict and spine-lazy. -homepage: https://github.com/sergv/radix-tree+license:       BSD3+license-file:  LICENSE +author:        Sergey Vinokurov, Oleksii Divak+maintainer:    Oleksii Divak <frozenwitness@gmail.com>+copyright:     (c) 2018 Sergey Vinokurov++cabal-version: 2.0+build-type:    Simple++homepage:      https://github.com/sergv/radix-tree+ source-repository head-    type: git-    location: https://github.com/sergv/radix-tree.git+  type: git+  location: https://github.com/sergv/radix-tree.git  library-  exposed-modules:-    Data.RadixTree-    Data.RadixTree.Internal-  hs-source-dirs:-    src-  build-depends:-    base >= 4.9 && < 5,-    bytestring,-    containers,-    deepseq,-    primitive-  default-language:-    Haskell2010-  ghc-options:-    -Wall-    -fwarn-name-shadowing-    -fno-warn-type-defaults-  if impl(ghc >= 8.0)-    ghc-options:-      -Wcompat-      -Whi-shadowing-      -Widentities-      -Wincomplete-record-updates-      -Wincomplete-uni-patterns-      -Wmissing-exported-signatures-  if impl(ghc >= 8.2)-    ghc-options:-      -Wcpp-undef-      -Wmissing-home-modules-      -Wunbanged-strict-patterns+  exposed-modules:  Data.Patricia.Word.Lazy+                    Data.Patricia.Word.Lazy.Debug+                    Data.Patricia.Word.Lazy.TH+                    Data.Patricia.Word.Lazy.Unsafe+                    Data.Patricia.Word.Strict+                    Data.Patricia.Word.Strict.Debug+                    Data.Patricia.Word.Strict.TH+                    Data.Patricia.Word.Strict.Unsafe -test-suite radix-tree-test-  type:-    exitcode-stdio-1.0-  main-is:-    test/TestMain.hs-  build-depends:-    HUnit,-    QuickCheck,-    base >= 4.9 && < 5,-    bytestring,-    containers,-    tasty,-    tasty-hunit,-    tasty-quickcheck,-    radix-tree-  default-language:-    Haskell2010-  ghc-options:-    -rtsopts-    -Wall-    -fwarn-name-shadowing-    -fno-warn-type-defaults-  if impl(ghc >= 8.0)-    ghc-options:-      -Wall-missed-specialisations-      -Wcompat-      -Whi-shadowing-      -Widentities-      -Wincomplete-record-updates-      -Wincomplete-uni-patterns-      -Wmissing-exported-signatures-  if impl(ghc >= 8.2)-    ghc-options:-      -Wcpp-undef-      -Wmissing-home-modules-      -Wunbanged-strict-patterns+                    Data.RadixTree.Word8.Key+                    Data.RadixTree.Word8.Key.Unsafe+                    Data.RadixTree.Word8.Lazy+                    Data.RadixTree.Word8.Lazy.Debug+                    Data.RadixTree.Word8.Lazy.TH+                    Data.RadixTree.Word8.Lazy.Unsafe+                    Data.RadixTree.Word8.Strict+                    Data.RadixTree.Word8.Strict.Debug+                    Data.RadixTree.Word8.Strict.TH+                    Data.RadixTree.Word8.Strict.Unsafe -benchmark radix-tree-bench-  type:-    exitcode-stdio-1.0-  main-is:-    bench/RadixTreeBench.hs-  hs-source-dirs:-    . bench-  build-depends:-    base >= 4.9 && < 5,-    bytestring,-    containers,-    deepseq,-    gauge >= 0.2.3,-    hashtables,-    radix-tree,-    text,-    unordered-containers-  default-language:-    Haskell2010-  ghc-options:-    -rtsopts-    -Wall-    -fwarn-name-shadowing-    -fno-warn-type-defaults-  if impl(ghc >= 8.0)-    ghc-options:-      -Wcompat-      -Whi-shadowing-      -Widentities-      -Wincomplete-record-updates-      -Wincomplete-uni-patterns-      -Wmissing-exported-signatures-  if impl(ghc >= 8.2)-    ghc-options:-      -Wcpp-undef-      -Wmissing-home-modules-      -Wunbanged-strict-patterns+                    Data.Radix1Tree.Word8.Key+                    Data.Radix1Tree.Word8.Key.Unsafe+                    Data.Radix1Tree.Word8.Lazy+                    Data.Radix1Tree.Word8.Lazy.Debug+                    Data.Radix1Tree.Word8.Lazy.TH+                    Data.Radix1Tree.Word8.Lazy.Unsafe+                    Data.Radix1Tree.Word8.Strict+                    Data.Radix1Tree.Word8.Strict.Debug+                    Data.Radix1Tree.Word8.Strict.TH+                    Data.Radix1Tree.Word8.Strict.Unsafe++                    Data.Zebra.Word+                    Data.Zebra.Word.Debug+                    Data.Zebra.Word.Unsafe++  other-modules:    Data.ByteArray.NonEmpty++                    Data.Patricia.Word.Common+                    Data.Patricia.Word.Conversion+                    Data.Patricia.Word.Debug+                    Data.Patricia.Word.Lazy.Internal+                    Data.Patricia.Word.Strict.Internal++                    Data.RadixNTree.Word8.Common+                    Data.RadixNTree.Word8.Conversion+                    Data.RadixNTree.Word8.Debug+                    Data.RadixNTree.Word8.Key+                    Data.RadixNTree.Word8.Lazy+                    Data.RadixNTree.Word8.Lazy.Debug+                    Data.RadixNTree.Word8.Lazy.TH+                    Data.RadixNTree.Word8.Strict+                    Data.RadixNTree.Word8.Strict.Debug+                    Data.RadixNTree.Word8.Strict.TH++                    Data.Zebra.Word.Internal++                    Numeric.Long++                    Radix.Common+                    Radix.Exception+                    Radix.Word8.Common+                    Radix.Word8.Debug+                    Radix.Word8.Foundation+                    Radix.Word.Common+                    Radix.Word.Debug+                    Radix.Word.Foundation++  hs-source-dirs:   src++  build-depends:    base             >= 4.12 && < 5+                  , bytestring       >= 0.10.4 && < 0.13+                  , deepseq          >= 1.4.3 && < 1.6+                  , primitive        >= 0.7 && < 0.10+                  , template-haskell >= 2.17 && < 3+                  , text             >= 2.0 && < 2.2++  default-language: Haskell2010++  ghc-options:      -Wall++test-suite properties+  type:             exitcode-stdio-1.0++  main-is:          Main.hs++  other-modules:    No.Set.Word+                    No.Tree++                    Test.Kit++                    Test.Patricia.Word.Lazy+                    Test.Patricia.Word.Sample+                    Test.Patricia.Word.Strict++                    Test.RadixNTree.Word8.Key+                    Test.RadixNTree.Word8.Sample++                    Test.RadixTree.Word8.Lazy+                    Test.RadixTree.Word8.Strict++                    Test.Random++                    Test.Zebra.Word+                    Test.Zebra.Word.Sample++  hs-source-dirs:   no+                  , test/properties++  ghc-options:      -Wall++  build-depends:    base+                  , bytestring+                  , containers >= 0.5 && < 0.8+                  , hspec      >= 2 && < 3+                  , primitive+                  , radix-tree+                  , random     >= 1.2.0 && < 1.3+                  , text++  default-language: Haskell2010
+ src/Data/ByteArray/NonEmpty.hs view
@@ -0,0 +1,152 @@+{-# LANGUAGE BangPatterns+           , RankNTypes+           , ScopedTypeVariables+           , UnboxedTuples #-}++module Data.ByteArray.NonEmpty+  ( Step (..)++  , fromStep+  , toNonEmpty+  , toList++  , dropByteArray++  , appendByteArray+  , dropAppendByteArray+  , fromStepAppend++  , splitByteArray+  ) where++import           Control.Monad.ST+import           Data.Primitive.ByteArray+import           Data.List.NonEmpty (NonEmpty (..))+import           Data.Word++++-- | Single step of destroying a key.+data Step a b = More a b+              | Done++{-# INLINE fromStep #-}+fromStep :: (x -> Step Word8 x) -> Word8 -> x -> ByteArray+fromStep (more :: x -> Step Word8 x) = \w0 -> go 1 (\marr -> writeByteArray marr 0 w0)+  where+    go :: Int -> (forall s. MutableByteArray s -> ST s ()) -> x -> ByteArray+    go !n write s =+      case more s of+        More w s' ->+          let write' marr = do+                write marr+                writeByteArray marr n w++          in go (n + 1) write' s'++        Done      ->+          runST $ do+            marr <- newByteArray n+            write marr+            unsafeFreezeByteArray marr++++{-# INLINE toNonEmpty #-}+toNonEmpty :: ByteArray -> NonEmpty Word8+toNonEmpty arr = indexByteArray arr 0 :| toListFrom 1 arr++{-# INLINE toList #-}+toList :: ByteArray -> [Word8]+toList = toListFrom 0++{-# INLINE toListFrom #-}+toListFrom :: Int -> ByteArray -> [Word8]+toListFrom n0 arr = go n0+  where+    go n+      | n >= sizeofByteArray arr = []+      | otherwise                = indexByteArray arr n : go (n + 1)++++dropByteArray :: Int -> ByteArray -> ByteArray+dropByteArray n arr =+  runST $ do+    let len = sizeofByteArray arr - n+    mbrr <- newByteArray len+    copyByteArray mbrr 0 arr n len+    unsafeFreezeByteArray mbrr++++appendByteArray :: ByteArray -> ByteArray -> ByteArray+appendByteArray arr brr =+  runST $ do+    let alen = sizeofByteArray arr+        blen = sizeofByteArray brr+    mcrr <- newByteArray (alen + blen)+    copyByteArray mcrr 0    arr 0 alen+    copyByteArray mcrr alen brr 0 blen+    unsafeFreezeByteArray mcrr++++dropAppendByteArray :: Int -> ByteArray -> ByteArray -> ByteArray+dropAppendByteArray n arr brr =+  runST $ do+    let alen = sizeofByteArray arr - n+        blen = sizeofByteArray brr+    mcrr <- newByteArray (alen + blen)+    copyByteArray mcrr 0    arr n alen+    copyByteArray mcrr alen brr 0 blen+    unsafeFreezeByteArray mcrr++++{-# INLINE fromStepAppend #-}+fromStepAppend :: (x -> Step Word8 x) -> Word8 -> x -> ByteArray -> ByteArray+fromStepAppend (more :: x -> Step Word8 x) = \w0 s0 arr ->+  let go :: Int -> (forall s. MutableByteArray s -> ST s ()) -> x -> ByteArray+      go !n write s =+        case more s of+          More w s' ->+            let write' mbrr = do+                  writeByteArray mbrr n w+                  write mbrr++            in go (n + 1) write' s'++          Done      ->+            runST $ do+              let alen = sizeofByteArray arr+              mbrr <- newByteArray (n + alen)+              write mbrr+              copyByteArray mbrr n arr 0 alen+              unsafeFreezeByteArray mbrr++  in go 1 (\mbrr -> writeByteArray mbrr 0 w0) s0++++data Wrap = Wrap {-# UNPACK #-} !ByteArray {-# UNPACK #-} !ByteArray++splitByteArray :: Int -> Int -> ByteArray -> (# ByteArray, ByteArray #)+splitByteArray offset n arr =+  let f = runST $ do+            let alen = sizeofByteArray arr++            mbrr <- newByteArray n+            copyByteArray mbrr 0 arr offset n+            brr <- unsafeFreezeByteArray mbrr++            let clen = alen - n++            mcrr <- newByteArray clen+            copyByteArray mcrr 0 arr n clen+            crr <- unsafeFreezeByteArray mcrr++            pure $ Wrap brr crr++  in case f of+       Wrap brr crr -> (# brr, crr #)
+ src/Data/Patricia/Word/Common.hs view
@@ -0,0 +1,9 @@+module Data.Patricia.Word.Common+  ( Lookup (..)+  ) where++++-- | Key together with the value.+data Lookup a = Lookup {-# UNPACK #-} !Word a+                deriving Show
+ src/Data/Patricia/Word/Conversion.hs view
@@ -0,0 +1,30 @@+module Data.Patricia.Word.Conversion where++import           Data.Patricia.Word.Lazy.Internal as Lazy+import           Data.Patricia.Word.Strict.Internal as Strict++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Create a lazy 'Lazy.Patricia' tree from a strict one.+--+--   The resulting tree does not share its data representation with the original.+toLazy :: StrictPatricia a -> LazyPatricia a+toLazy t =+  case t of+    Strict.Bin p l r -> Lazy.Bin p (toLazy l) (toLazy r)+    Strict.Tip k a   -> Lazy.Tip k a+    Strict.Nil       -> Lazy.Nil++++-- | \(\mathcal{O}(n)\).+--   Create a strict 'Strict.Patricia' tree from a lazy one.+--+--   The resulting tree does not share its data representation with the original.+toStrict :: LazyPatricia a -> StrictPatricia a+toStrict t =+  case t of+    Lazy.Bin p l r -> Strict.Bin p (toStrict l) (toStrict r)+    Lazy.Tip k a   -> Strict.Tip k a+    Lazy.Nil       -> Strict.Nil
+ src/Data/Patricia/Word/Debug.hs view
@@ -0,0 +1,24 @@+module Data.Patricia.Word.Debug+  ( Validity (..)+  , Reason (..)+  ) where++import           Radix.Word.Foundation++++-- | Whether the tree is well-formed.+data Validity = Valid+              | Invalid Reason+                deriving Show++-- | Reason for why the tree is considered malformed.+data Reason = -- | Prefix is @0@.+              ZeroPrefix+            | -- | Prefix below diverges from the prefix above.+              PrefixBelow Prefix Prefix+              -- | Key diverges the prefix above.+            | KeyBelow Prefix Key+              -- | One of the branches is empty.+            | MalformedBin Prefix+              deriving Show
+ src/Data/Patricia/Word/Lazy.hs view
@@ -0,0 +1,246 @@+{-|+    @'LazyPatricia' a@ is a spine-lazy big-endian PATRICIA tree, a compressed+    trie with a radix of 2, using 'Word's as keys.++    == Laziness++    Evaluating any particular entry in the tree to WHNF forces the evaluation+    of the part of the spine leading up to that entry to normal form.++    == Performance++    Each function's time complexity is provided in the documentation.++    Laziness-amortized functions specify two time complexities:+    time to construct the return value (denoted with a \(\texttt{+}\)) and time to+    fully apply the function to the tree.++    \(n\) refers to the number of evaluated entries in the resulting tree.+    Parts of the tree are denoted using subscripts: \(n_L\) refers to the left side,+    \(n_R\) to the right side, \(n_I\) to a range (interval), and+    \(n_M\) to entries collected with the use of a 'Monoid'.++    \(W\) is the size of 'Word' in bits, i.e. @'Data.Bits.finiteBitSize' (0 :: 'Word')@.++    == Implementation++    See the implementation section in "Data.Patricia.Word.Strict".+ -}++module Data.Patricia.Word.Lazy+  ( LazyPatricia+  , Patricia++    -- * Construct+  , empty+  , singleton++    -- ** Convert+  , toStrict++    -- * Single-key+    -- ** Lookup+  , Data.Patricia.Word.Lazy.Internal.lookup+  , Data.Patricia.Word.Lazy.Internal.find+  , member++    -- ** Insert+  , insert+  , insertWith++    -- ** Map+  , adjust++    -- ** Delete+  , delete++    -- ** Update+  , update++  , alter++    -- ** Take+  , splitLookup++    -- * Directional+    -- ** Lookup+  , Lookup (..)+  , lookupL+  , lookupR++    -- ** Map+    -- | === Left+  , adjustL+  , adjustLWithKey++    -- | === Right+  , adjustR+  , adjustRWithKey++    -- ** Delete+  , deleteL+  , deleteR++    -- ** Update+    -- | === Left+  , updateL+  , updateLWithKey++    -- | === Right+  , updateR+  , updateRWithKey++    -- ** Take+    -- | === Left+  , takeL+  , splitL++    -- | === Right+  , takeR+  , splitR++    -- * Range+  , Range (Range)++    -- ** Map+  , adjustRange+  , adjustRangeWithKey++    -- ** Delete+  , deleteRange++    -- ** Update+  , updateRange+  , updateRangeWithKey++    -- ** Take+  , takeRange++    -- * Edges++    -- ** Lookup+    -- | === Min+  , lookupMin+  , lookupMinWithKey++    -- | === Max+  , lookupMax+  , lookupMaxWithKey++    -- ** Map+    -- | === Min+  , adjustMin+  , adjustMinWithKey++    -- | === Max+  , adjustMax+  , adjustMaxWithKey++    -- ** Delete+  , deleteMin+  , deleteMax++    -- ** Update+    -- | === Min+  , updateMin+  , updateMinWithKey++    -- | === Max+  , updateMax+  , updateMaxWithKey++    -- ** View+    -- | === Min+  , ViewL (..)+  , minView++    -- | === Max+  , ViewR (..)+  , maxView++    -- * Full tree+    -- ** Size+  , Data.Patricia.Word.Lazy.Internal.null+  , size++    -- ** Map+  , Data.Patricia.Word.Lazy.Internal.map+  , mapWithKey++    -- ** Fold+    -- | === Left-to-right+  , Data.Patricia.Word.Lazy.Internal.foldl+  , Data.Patricia.Word.Lazy.Internal.foldl'+  , foldlWithKey+  , foldlWithKey'++    -- | === Right-to-left+  , Data.Patricia.Word.Lazy.Internal.foldr+  , Data.Patricia.Word.Lazy.Internal.foldr'+  , foldrWithKey+  , foldrWithKey'++    -- | === Monoid+  , Data.Patricia.Word.Lazy.Internal.foldMap+  , foldMapWithKey++    -- ** Traverse+  , Data.Patricia.Word.Lazy.Internal.traverse+  , traverseWithKey++    -- ** Filter+    -- | === One side+  , Data.Patricia.Word.Lazy.Internal.filter+  , filterWithKey++  , mapMaybe+  , mapMaybeWithKey++    -- | === Both sides+  , partition+  , partitionWithKey++  , mapEither+  , mapEitherWithKey++    -- ** Comparison+  , PartialOrdering (..)+  , Data.Patricia.Word.Lazy.Internal.compare++    -- ** Union+  , union+  , unionL+  , unionWith+  , unionWithKey++    -- ** Difference+  , difference+  , differenceWith+  , differenceWithKey++    -- ** Intersection+  , disjoint+  , intersection+  , intersectionL+  , intersectionWith+  , intersectionWithKey++    -- ** Merge+    -- | See 'Data.Patricia.Word.Lazy.Unsafe.merge'.+  ) where++import           Data.Patricia.Word.Common+import           Data.Patricia.Word.Conversion+import           Data.Patricia.Word.Lazy.Internal+import           Radix.Common+import           Radix.Word.Common++++-- | \(\mathcal{O}(1)\). Empty tree.+empty :: Patricia a+empty = Nil++-- | \(\mathcal{O}(1)\). Tree with a single entry.+singleton :: Word -> a -> Patricia a+singleton = Tip
+ src/Data/Patricia/Word/Lazy/Debug.hs view
@@ -0,0 +1,72 @@+{-|+    Safe functions for datatype introspection.+ -}++module Data.Patricia.Word.Lazy.Debug+  ( -- * Show+    showsTree++    -- * Validate+  , Validity (..)+  , Reason (..)+  , validate+  ) where++import           Data.Patricia.Word.Debug+import           Data.Patricia.Word.Lazy.Internal+import           Numeric.Long+import           Radix.Word.Debug++++-- | \(\mathcal{O}(n)\).+--   Shows the internal structure of the tree.+showsTree :: (a -> ShowS) -> Patricia a -> ShowS+showsTree f = go 0+  where+    go i t =+      mappend (replicate i ' ') .+        case t of+          Bin p l r ->+            showString "Bin " . showPrefix p . showChar '\n'+                              . go (i + 2) l . showChar '\n'+                              . go (i + 2) r++          Tip k a   ->+            showString "Tip " . showLongHex k . showString " => " . f a++          Nil       -> showString "Nil"++++-- | \(\mathcal{O}(n)\).+--   Checks whether the tree is well-formed.+validate :: Patricia a -> Validity+validate t =+  case t of+    Bin p l r+      | p == 0    -> Invalid ZeroPrefix+      | otherwise ->+          case go L p l of+            Valid -> go R p r+            err   -> err++    Tip _ _ -> Valid++    Nil -> Valid+  where+    go s q x =+      case x of+        Bin p l r+          | p == 0                 -> Invalid ZeroPrefix+          | not $ validBelow q s p -> Invalid $ PrefixBelow q p+          | otherwise              ->+              case go L p l of+                Valid -> go R p r+                err   -> err++        Tip k _+          | not $ validBelow q s k -> Invalid $ KeyBelow q k+          | otherwise              -> Valid++        Nil -> Invalid $ MalformedBin q
+ src/Data/Patricia/Word/Lazy/Internal.hs view
@@ -0,0 +1,2583 @@+{-# LANGUAGE BangPatterns+           , DeriveLift+           , GADTs+           , RankNTypes+           , ScopedTypeVariables+           , UnboxedTuples #-}++module Data.Patricia.Word.Lazy.Internal+  ( LazyPatricia+  , Patricia (..)++  , Data.Patricia.Word.Lazy.Internal.null+  , size++  , Data.Patricia.Word.Lazy.Internal.map+  , mapWithKey++  , Data.Patricia.Word.Lazy.Internal.foldl+  , Data.Patricia.Word.Lazy.Internal.foldl'+  , foldlWithKey+  , foldlWithKey'++  , Data.Patricia.Word.Lazy.Internal.foldr+  , Data.Patricia.Word.Lazy.Internal.foldr'+  , foldrWithKey+  , foldrWithKey'++  , Data.Patricia.Word.Lazy.Internal.foldMap+  , foldMapWithKey++  , Data.Patricia.Word.Lazy.Internal.traverse+  , traverseWithKey++  , union+  , unionL+  , unionWith+  , unionWithKey++  , difference+  , differenceWith+  , differenceWithKey++  , Data.Patricia.Word.Lazy.Internal.compare++  , disjoint+  , intersection+  , intersectionL+  , intersectionWith+  , intersectionWithKey++  , merge++  , Data.Patricia.Word.Lazy.Internal.lookup+  , Data.Patricia.Word.Lazy.Internal.find+  , member+  , takeOne++  , insert+  , insertWith++  , adjust++  , delete++  , update++  , alter++  , lookupL+  , lookupR++  , adjustL+  , adjustLWithKey++  , adjustR+  , adjustRWithKey++  , deleteL+  , deleteR++  , updateL+  , updateR+  , updateLWithKey+  , updateRWithKey++  , adjustRange+  , unsafeAdjustRange++  , adjustRangeWithKey+  , unsafeAdjustRangeWithKey++  , deleteRange+  , unsafeDeleteRange++  , updateRange+  , unsafeUpdateRange++  , updateRangeWithKey+  , unsafeUpdateRangeWithKey++  , takeRange+  , unsafeTakeRange++  , takeL+  , takeR++  , splitL+  , splitR+  , splitLookup++  , Data.Patricia.Word.Lazy.Internal.filter+  , filterWithKey++  , mapMaybe+  , mapMaybeWithKey++  , partition+  , partitionWithKey++  , mapEither+  , mapEitherWithKey++  , lookupMin+  , lookupMinWithKey+  , lookupMax+  , lookupMaxWithKey++  , unsafeLookupMin+  , unsafeLookupMinWithKey+  , unsafeLookupMax+  , unsafeLookupMaxWithKey++  , deleteMin+  , deleteMax++  , adjustMin+  , adjustMinWithKey+  , adjustMax+  , adjustMaxWithKey++  , updateMin+  , updateMinWithKey+  , updateMax+  , updateMaxWithKey++  , ViewL (..)+  , minView+  , unsafeMinView++  , ViewR (..)+  , maxView+  , unsafeMaxView+  ) where++import           Data.Patricia.Word.Common+import           Radix.Common+import           Radix.Exception+import           Radix.Word.Common+import           Radix.Word.Foundation++import           Control.Applicative+import           Control.DeepSeq+import           Control.Exception (throw)+import           Data.Bits+import           Data.Foldable+import           Data.Functor.Classes+import           Language.Haskell.TH.Syntax (Lift)+import           Text.Read+import           Text.Show++++-- | Convenience synonym.+type LazyPatricia = Patricia++-- | Spine-lazy PATRICIA tree.+data Patricia a = Bin+                    {-# UNPACK #-} !Prefix+                    (Patricia a)          -- ^ Masked bit is @0@.+                    (Patricia a)          -- ^ Masked bit is @1@.++                | Tip+                    {-# UNPACK #-} !Key+                    a++                | Nil -- ^ Invariant: only allowed as the root of the tree.+                  deriving Lift++instance Show a => Show (Patricia a) where+  showsPrec = liftShowsPrec showsPrec showList++instance Show1 Patricia where+  liftShowsPrec showsPrec_ showList_ _ t =+    showListWith (liftShowsPrec showsPrec_ showList_ 0) $+      foldrWithKey (\k a -> (:) (k, a)) [] t++instance Read a => Read (Patricia a) where+  readPrec = liftReadPrec readPrec readListPrec++instance Read1 Patricia where+  liftReadPrec readPrec_ readList_ =+    fmap (Data.Foldable.foldl' (\z (k, a) -> insert k a z) Nil)+      (liftReadListPrec readPrec_ readList_)+++instance Eq a => Eq (Patricia a) where+  (==) = liftEq (==)++instance Eq1 Patricia where+  liftEq eq = go+    where+      go l r =+        case l of+          Bin p xl xr ->+            case r of+              Bin q yl yr -> p == q && go xl yl && go xr yr+              _           -> False++          Tip kA a ->+            case r of+              Tip kB b -> kA == kB && eq a b+              _        -> False++          Nil ->+            case r of+              Nil -> True+              _   -> False+++instance Functor Patricia where+  fmap = Data.Patricia.Word.Lazy.Internal.map++instance Foldable Patricia where+  foldl = Data.Patricia.Word.Lazy.Internal.foldl+  foldr = Data.Patricia.Word.Lazy.Internal.foldr+  foldMap = Data.Patricia.Word.Lazy.Internal.foldMap++  foldl' = Data.Patricia.Word.Lazy.Internal.foldl'+  foldr' = Data.Patricia.Word.Lazy.Internal.foldr'++  null = Data.Patricia.Word.Lazy.Internal.null+  length = fromIntegral . size++instance Traversable Patricia where+  traverse = Data.Patricia.Word.Lazy.Internal.traverse+++instance NFData a => NFData (Patricia a) where+  rnf = liftRnf rnf++instance NFData1 Patricia where+  liftRnf nf = go+    where+      go t =+        case t of+          Bin _ l r -> go l `seq` go r+          Tip _ a   -> nf a+          Nil       -> ()++++{-# INLINE join #-}+-- | Knowing that the prefices of two non-'Nil' trees disagree, construct a 'Bin'.+join :: Prefix -> Patricia a -> Prefix -> Patricia a -> Patricia a+join p0 t0 p1 t1 =+  let m = branchingBit p0 p1++      p = mask p0 m .|. m++  in if zeroBit p0 m+       then Bin p t0 t1+       else Bin p t1 t0++{-# INLINE safeJoin #-}+-- | Knowing that the prefices of two trees disagree, construct a 'Bin'.+safeJoin :: Prefix -> Patricia a -> Prefix -> Patricia a -> Patricia a+safeJoin _  Nil _  t1  = t1+safeJoin _  t0  _  Nil = t0+safeJoin p0 t0  p1 t1  = join p0 t0 p1 t1++{-# INLINE rebin #-}+-- | Reconstruct a 'Bin' knowing that either of the sides may now be a 'Nil'.+rebin :: Prefix -> Patricia a -> Patricia a -> Patricia a+rebin p l r =+  case l of+    Nil -> r+    _   ->+      case r of+        Nil -> l+        _   -> Bin p l r++{-# INLINE rebinL #-}+-- | Reconstruct a 'Bin' knowing that the left side may now be a 'Nil'.+rebinL :: Prefix -> Patricia a -> Patricia a -> Patricia a+rebinL p l r =+  case l of+    Nil -> r+    _   -> Bin p l r+++{-# INLINE rebinR #-}+-- | Reconstruct a 'Bin' knowing that the right side may now be a 'Nil'.+rebinR :: Prefix -> Patricia a -> Patricia a -> Patricia a+rebinR p l r =+  case r of+    Nil -> l+    _   -> Bin p l r+++{-# INLINE retip #-}+-- | Reconstruct a 'Tip' knowing that the value may not be there anymore.+retip :: Key -> Maybe a -> Patricia a+retip w (Just a) = Tip w a+retip _ Nothing  = Nil++++-- | \(\mathcal{O}(1)\).+--   Check if the tree is empty.+null :: Patricia a -> Bool+null Nil = True+null _   = False++-- | \(\mathcal{O}(n)\).+--   Calculate the number of elements stored in the tree.+--   The returned number is guaranteed to be non-negative.+size :: Patricia a -> Int+size t =+  case t of+    Bin _ l r -> let !m = size l+                     !n = size r+                 in m + n++    Tip _ _   -> 1++    Nil       -> 0++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree.+map :: (a -> b) -> Patricia a -> Patricia b+map f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) (go r)+        Tip k a   -> Tip k (f a)+        Nil       -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree.+mapWithKey :: (Word -> a -> b) -> Patricia a -> Patricia b+mapWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) (go r)+        Tip k a   -> Tip k (f k a)+        Nil       -> Nil++++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldl :: (b -> a -> b) -> b -> Patricia a -> b+foldl f = go+  where+    go z t =+      case t of+        Bin _ l r -> go (go z l) r+        Tip _ a   -> f z a+        Nil       -> z++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldlWithKey :: (b -> Word -> a -> b) -> b -> Patricia a -> b+foldlWithKey f = go+  where+    go z t =+      case t of+        Bin _ l r -> go (go z l) r+        Tip k a   -> f z k a+        Nil       -> z++++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldl' :: (b -> a -> b) -> b -> Patricia a -> b+foldl' f = go+  where+    go !z t =+      case t of+        Bin _ l r -> let !z' = go z l+                     in go z' r+        Tip _ a   -> f z a+        Nil       -> z++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldlWithKey' :: (b -> Word -> a -> b) -> b -> Patricia a -> b+foldlWithKey' f = go+  where+    go !z t =+      case t of+        Bin _ l r -> let !z' = go z l+                     in go z' r+        Tip k a   -> f z k a+        Nil       -> z++++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldr :: (a -> b -> b) -> b -> Patricia a -> b+foldr f = go+  where+    go z t =+      case t of+        Bin _ l r -> go (go z r) l+        Tip _ a   -> f a z+        Nil       -> z++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldrWithKey :: (Word -> a -> b -> b) -> b -> Patricia a -> b+foldrWithKey f = go+  where+    go z t =+      case t of+        Bin _ l r -> go (go z r) l+        Tip k a   -> f k a z+        Nil       -> z++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldr' :: (a -> b -> b) -> b -> Patricia a -> b+foldr' f = go+  where+    go !z t =+      case t of+        Bin _ l r -> let !z' = go z r+                     in go z' l+        Tip _ a   -> f a z+        Nil       -> z++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldrWithKey' :: (Word -> a -> b -> b) -> b -> Patricia a -> b+foldrWithKey' f = go+  where+    go !z t =+      case t of+        Bin _ l r -> let !z' = go z r+                     in go z' l+        Tip k a   -> f k a z+        Nil       -> z++++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMap :: Monoid m => (a -> m) -> Patricia a -> m+foldMap f = go+  where+    go t =+      case t of+        Bin _ l r -> go l <> go r+        Tip _ a   -> f a+        Nil       -> mempty++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMapWithKey :: Monoid m => (Word -> a -> m) -> Patricia a -> m+foldMapWithKey f = go+  where+    go t =+      case t of+        Bin _ l r -> go l <> go r+        Tip k a   -> f k a+        Nil       -> mempty++++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverse :: Applicative f => (a -> f b) -> Patricia a -> f (Patricia b)+traverse f = go+  where+    go t =+      case t of+        Bin p l r -> liftA2 (Bin p) (go l) (go r)+        Tip k a   -> Tip k <$> f a+        Nil       -> pure Nil++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverseWithKey :: Applicative f => (Word -> a -> f b) -> Patricia a -> f (Patricia b)+traverseWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> liftA2 (Bin p) (go l) (go r)+        Tip k a   -> Tip k <$> f k a+        Nil       -> pure Nil++++type UBin a = (# Prefix, Patricia a, Patricia a #)++type UTip a = (# Word, a #)++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Unbiased union of two trees.+union :: Patricia a -> Patricia a -> Patricia a+union = anyAny+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA -> binAny (# pA, lA, rA #) tA tB++        Tip kA _ -> tipAny kA tA tB++        Nil -> tB++    tipAny kA tA tB =+      case tB of+        Bin pB lB rB -> tipBin kA tA (# pB, lB, rB #) tB++        Tip kB _+          | kA == kB  -> tA+          | otherwise -> join kA tA kB tB++        Nil -> tA++    binAny uA tA tB =+      case tB of+        Bin pB lB rB -> binBin uA tA (# pB, lB, rB #) tB++        Tip kB _ -> tipBin kB tB uA tA++        Nil -> tA++    tipBin kA tA (# pB, lB, rB #) tB+      | beyond pB kA = join kA tA pB tB+      | kA < pB      = Bin pB (tipAny kA tA lB) rB+      | otherwise    = Bin pB lB (tipAny kA tA rB)++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = join pA tA pB tB++      in case Prelude.compare pA pB of+           EQ                  -> Bin pA (anyAny lA lB) (anyAny rA rB)++           LT | pB <= upper pA -> Bin pA lA (binAny uB tB rA)+              | pA >= lower pB -> Bin pB (binAny uA tA lB) rB+              | otherwise      -> no++           GT | pA <= upper pB -> Bin pB lB (binAny uA tA rB)+              | pB >= lower pA -> Bin pA (binAny uB tB lA) rA+              | otherwise      -> no++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Left-biased union of two trees.+unionL :: Patricia a -> Patricia a -> Patricia a+unionL =+  union_ $ \s k a b ->+    let !(# c #) = case s of+                     L -> (# a #)+                     R -> (# b #)+    in Tip k c++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Union of two trees with a combining function.+unionWith+  :: (a -> a -> a)+  -> Patricia a+  -> Patricia a+  -> Patricia a+unionWith f =+  union_ $ \s k a b ->+    let !(# c #) = case s of+                     L -> (# f a b #)+                     R -> (# f b a #)+    in Tip k c++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Union of two trees with a combining function.+unionWithKey+  :: (Word -> a -> a -> a)+  -> Patricia a+  -> Patricia a+  -> Patricia a+unionWithKey f =+  union_ $ \s k a b ->+    let !(# c #) = case s of+                     L -> (# f k a b #)+                     R -> (# f k b a #)+    in Tip k c++++{-# INLINE union_ #-}+union_+  :: (forall x y. S x y a a -> Key -> x -> y -> Patricia a)+  -> Patricia a+  -> Patricia a+  -> Patricia a+union_ f = anyAny L+  where+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Tip kA a -> tipAny s (# kA, a #) tA tB++        Nil -> tB++    tipAny s uA@(# kA, a #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #) tB++        Tip kB b+          | kA == kB  -> f s kA a b+          | otherwise -> join kA tA kB tB++        Nil -> tA++    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Tip kB b ->+          let !(# s' #) = other s+          in tipBin s' (# kB, b #) tB uA tA++        Nil -> tA++    tipBin s uA@(# kA, _ #) tA (# pB, lB, rB #) tB+      | beyond pB kA = join kA tA pB tB+      | kA < pB      = Bin pB (tipAny s uA tA lB) rB+      | otherwise    = Bin pB lB (tipAny s uA tA rB)++    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = join pA tA pB tB++      in case Prelude.compare pA pB of+           EQ                  -> Bin pA (anyAny s lA lB) (anyAny s rA rB)++           LT | pB <= upper pA -> let !(# s' #) = other s+                                  in Bin pA lA (binAny s' uB tB rA)+              | pA >= lower pB -> Bin pB (binAny s uA tA lB) rB+              | otherwise      -> no++           GT | pA <= upper pB -> Bin pB lB (binAny s uA tA rB)+              | pB >= lower pA -> let !(# s' #) = other s+                                  in Bin pA (binAny s' uB tB lA) rA+              | otherwise      -> no++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Difference of two trees.+difference :: Patricia a -> Patricia b -> Patricia a+difference =+  difference_ $ \_ _ _ _ ->+    Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Difference of two trees with a combining function.+differenceWith+  :: (a -> b -> Maybe a)+  -> Patricia a+  -> Patricia b+  -> Patricia a+differenceWith f =+  difference_ $ \s k a b ->+    retip k $ case s of+                L -> f a b+                R -> f b a++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Difference of two trees with a combining function.+differenceWithKey+  :: (Word -> a -> b -> Maybe a)+  -> Patricia a+  -> Patricia b+  -> Patricia a+differenceWithKey f =+  difference_ $ \s k a b ->+    retip k $ case s of+                L -> f k a b+                R -> f k b a++++{-# INLINE difference_ #-}+difference_+  :: (forall x y. S x y a b -> Key -> x -> y -> Patricia a)+  -> Patricia a+  -> Patricia b+  -> Patricia a+difference_ (f :: forall n o. S n o x y -> Key -> n -> o -> Patricia x) = anyAny L+  where+    anyAny+      :: forall a b. S a b x y -> Patricia a -> Patricia b -> Patricia x+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Tip kA a -> tipAny s (# kA, a #) tA tB++        Nil -> case s of+                 L -> tA+                 R -> tB++    tipAny+      :: forall a b. S a b x y -> UTip a -> Patricia a -> Patricia b -> Patricia x+    tipAny s uA@(# kA, a #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #) tB++        Tip kB b+          | kA == kB  -> f s kA a b+          | otherwise -> case s of+                           L -> tA+                           R -> tB++        Nil -> case s of+                 L -> tA+                 R -> tB++    binAny+      :: forall a b. S a b x y -> UBin a -> Patricia a -> Patricia b -> Patricia x+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Tip kB b -> let !(# s' #) = other s+                    in tipBin s' (# kB, b #) tB uA tA++        Nil -> case s of+                 L -> tA+                 R -> tB++    tipBin+      :: forall a b. S a b x y -> UTip a -> Patricia a -> UBin b -> Patricia b -> Patricia x+    tipBin s uA@(# kA, _ #) tA (# pB, lB, rB #) tB+      | beyond pB kA = case s of+                         L -> tA+                         R -> tB++      | kA < pB      = case s of+                         L -> tipAny s uA tA lB+                         R -> rebinL pB (tipAny s uA tA lB) rB++      | otherwise    = case s of+                         L -> tipAny s uA tA rB+                         R -> rebinR pB lB (tipAny s uA tA rB)++    binBin+      :: forall a b. S a b x y -> UBin a -> Patricia a -> UBin b -> Patricia b -> Patricia x+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = case s of+                 L -> tA+                 R -> tB++      in case Prelude.compare pA pB of+           EQ                  -> rebin pA (anyAny s lA lB) (anyAny s rA rB)++           LT | pB <= upper pA -> case s of+                                    L -> rebinR pA lA (binAny R uB tB rA)+                                    R -> binAny L uB tB rA++              | pA >= lower pB -> case s of+                                    L -> binAny s uA tA lB+                                    R -> rebinL pB (binAny s uA tA lB) rB++              | otherwise      -> no++           GT | pA <= upper pB -> case s of+                                    L -> binAny s uA tA rB+                                    R -> rebinR pB lB (binAny s uA tA rB)++              | pB >= lower pA -> case s of+                                    L -> rebinL pA (binAny R uB tB lA) rA+                                    R -> binAny L uB tB lA++              | otherwise      -> no++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Compare two trees with respect to set inclusion,+--   using the given equality function for intersecting keys.+--   If any intersecting keys hold unequal values, the trees are 'Incomparable'.+compare :: (a -> b -> Bool) -> Patricia a -> Patricia b -> PartialOrdering+compare (f :: x -> y -> Bool) = anyAny L+  where+    anyAny+      :: forall a b. S a b x y -> Patricia a -> Patricia b -> PartialOrdering+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Tip kA a -> tipAny s (# kA, a #) tA tB++        Nil -> case tB of+                 Nil -> Equal+                 _   -> Subset++    tipAny+      :: forall a b. S a b x y -> UTip a -> Patricia a -> Patricia b -> PartialOrdering+    tipAny s uA@(# kA, a #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #)++        Tip kB b+          | kA == kB  -> let eq = case s of+                                    L -> f a b+                                    R -> f b a+                         in if eq+                              then Equal+                              else Incomparable++          | otherwise -> Incomparable++        Nil -> Superset++    binAny+      :: forall a b. S a b x y -> UBin a -> Patricia a -> Patricia b -> PartialOrdering+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Tip kB b -> let !(# s' #) = other s+                    in tipBin s' (# kB, b #) tB uA++        Nil -> Superset++    tipBin+      :: forall a b. S a b x y -> UTip a -> Patricia a -> UBin b -> PartialOrdering+    tipBin s uA@(# kA, _ #) tA (# pB, lB, rB #) =+      if beyond pB kA+        then Incomparable+        else limit s . tipAny s uA tA $ if kA < pB+                                           then lB+                                           else rB++    binBin+      :: forall a b. S a b x y -> UBin a -> Patricia a -> UBin b -> Patricia b -> PartialOrdering+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> order (anyAny s lA lB) (anyAny s rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s+                               in limit s' $ binAny s' uB tB rA++           | pA >= lower pB -> limit s $ binAny s uA tA lB++           | otherwise      -> Incomparable++        GT | pA <= upper pB -> limit s $ binAny s uA tA rB++           | pB >= lower pA -> let !(# s' #) = other s++                               in limit s' $ binAny s' uB tB lA++           | otherwise      -> Incomparable++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Determine whether two trees' key sets are disjoint.+disjoint :: Patricia a -> Patricia b -> Bool+disjoint = anyAny+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA -> binAny (# pA, lA, rA #) tA tB++        Tip kA _ -> tipAny kA tA tB++        Nil -> True++    tipAny kA tA tB =+      case tB of+        Bin pB lB rB -> tipBin kA tA (# pB, lB, rB #)++        Tip kB _ -> kA /= kB++        Nil -> True++    binAny :: forall a b. UBin a -> Patricia a -> Patricia b -> Bool+    binAny uA tA tB =+      case tB of+        Bin pB lB rB -> binBin uA tA (# pB, lB, rB #) tB++        Tip kB _ -> tipBin kB tB uA++        Nil -> True++    tipBin kA tA (# pB, lB, rB #)+      | beyond pB kA = True+      | otherwise    = tipAny kA tA $ if kA < pB+                                        then lB+                                        else rB++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> anyAny lA lB && anyAny rA rB++        LT | pB <= upper pA -> binAny uB tB rA+           | pA >= lower pB -> binAny uA tA lB+           | otherwise      -> True++        GT | pA <= upper pB -> binAny uA tA rB+           | pB >= lower pA -> binAny uB tB lA+           | otherwise      -> True++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Unbiased intersection of two trees.+intersection :: Patricia a -> Patricia a -> Patricia a+intersection = anyAny+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA -> binAny (# pA, lA, rA #) tA tB++        Tip kA _ -> tipAny kA tA tB++        Nil -> Nil++    tipAny kA tA tB =+      case tB of+        Bin pB lB rB -> tipBin kA tA (# pB, lB, rB #)++        Tip kB _+          | kA == kB  -> tA+          | otherwise -> Nil++        Nil -> Nil++    binAny uA tA tB =+      case tB of+        Bin pB lB rB -> binBin uA tA (# pB, lB, rB #) tB++        Tip kB _ -> tipBin kB tB uA++        Nil -> Nil++    tipBin kA tA (# pB, lB, rB #)+      | beyond pB kA = Nil+      | otherwise    = tipAny kA tA $ if kA < pB+                                        then lB+                                        else rB++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny lA lB) (anyAny rA rB)++        LT | pB <= upper pA -> binAny uB tB rA+           | pA >= lower pB -> binAny uA tA lB+           | otherwise      -> Nil++        GT | pA <= upper pB -> binAny uA tA rB+           | pB >= lower pA -> binAny uB tB lA+           | otherwise      -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Left-biased intersection of two trees.+intersectionL :: Patricia a -> Patricia b -> Patricia a+intersectionL =+  intersection_ $ \s k a b ->+    let !(# c #) = case s of+                     L -> (# a #)+                     R -> (# b #)+    in Tip k c++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Intersection of two trees with a combining function.+intersectionWith+  :: (a -> b -> c)+  -> Patricia a+  -> Patricia b+  -> Patricia c+intersectionWith f =+  intersection_ $ \s k a b ->+    let !(# c #) = case s of+                     L -> (# f a b #)+                     R -> (# f b a #)+    in Tip k c++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   Intersection of two trees with a combining function.+intersectionWithKey+  :: (Word -> a -> b -> c)+  -> Patricia a+  -> Patricia b+  -> Patricia c+intersectionWithKey f =+  intersection_ $ \s k a b ->+    let !(# c #) = case s of+                     L -> (# f k a b #)+                     R -> (# f k b a #)+    in Tip k c++++{-# INLINE intersection_ #-}+intersection_+  :: (forall x y. S x y a b -> Key -> x -> y -> Patricia c)+  -> Patricia a+  -> Patricia b+  -> Patricia c+intersection_ (f :: forall n o. S n o x y -> Word -> n -> o -> Patricia c) =+  anyAny L+  where+    anyAny+      :: forall a b. S a b x y -> Patricia a -> Patricia b -> Patricia c+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Tip kA a -> tipAny s (# kA, a #) tA tB++        Nil -> Nil++    tipAny+      :: forall a b. S a b x y -> UTip a -> Patricia a -> Patricia b -> Patricia c+    tipAny s uA@(# kA, a #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #)++        Tip kB b+          | kA == kB  -> f s kA a b+          | otherwise -> Nil++        Nil -> Nil++    binAny+      :: forall a b. S a b x y -> UBin a -> Patricia a -> Patricia b -> Patricia c+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Tip kB b -> let !(# s' #) = other s+                    in tipBin s' (# kB, b #) tB uA++        Nil -> Nil++    tipBin+      :: forall a b. S a b x y -> UTip a -> Patricia a -> UBin b -> Patricia c+    tipBin s uA@(# kA, _ #) tA (# pB, lB, rB #)+      | beyond pB kA = Nil+      | otherwise    = tipAny s uA tA $ if kA < pB+                                          then lB+                                          else rB++    binBin+      :: forall a b. S a b x y -> UBin a -> Patricia a -> UBin b -> Patricia b -> Patricia c+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny s lA lB) (anyAny s rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s+                               in binAny s' uB tB rA+           | pA >= lower pB -> binAny s uA tA lB+           | otherwise      -> Nil++        GT | pA <= upper pB -> binAny s uA tA rB+           | pB >= lower pA -> let !(# s' #) = other s+                               in binAny s' uB tB lA+           | otherwise      -> Nil++++{-# INLINE merge #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A + n_B)\).+--   General merge of two trees.+--+--   Collision and single value functions __must__ return either+--   'Tip' with the respective key, or 'Nil'.+--+--   Subtree argument functions may return any tree, however the shape of said tree+--   __must__ be compatible with the prefix passed to the function.+--+--   This functions inlines when all argument functions are provided.+merge+  :: (Key -> a -> b -> Patricia c)                      -- ^ Collision+  -> (Key -> a -> Patricia c)                           -- ^ Single left value+  -> (Prefix -> Patricia a -> Patricia a -> Patricia c) -- ^ Left subtree+  -> (Key -> b -> Patricia c)                           -- ^ Single right value+  -> (Prefix -> Patricia b -> Patricia b -> Patricia c) -- ^ Right subtree+  -> Patricia a+  -> Patricia b+  -> Patricia c+merge (f :: Key -> x -> y -> Patricia c) oneX treeX oneY treeY = anyAny L+  where+    {-# INLINE side #-}+    side one tree t =+      case t of+        Bin p l r -> tree p l r+        Tip k a   -> one k a+        Nil       -> Nil++    sideX = side oneX treeX++    sideY = side oneY treeY++    sideA :: forall a b. S a b x y -> Patricia a -> Patricia c+    sideA s tA = case s of+                   L -> sideX tA+                   R -> sideY tA++    sideB :: forall a b. S a b x y -> Patricia b -> Patricia c+    sideB s tB = case s of+                   L -> sideY tB+                   R -> sideX tB++    anyAny+      :: forall a b. S a b x y -> Patricia a -> Patricia b -> Patricia c+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Tip kA a     -> tipAny s (# kA, a #) tA tB++        Nil          -> sideB s tB++    tipAny+      :: forall a b. S a b x y -> UTip a -> Patricia a -> Patricia b -> Patricia c+    tipAny s uA@(# kA, a #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #)++        Tip kB b+          | kA == kB  -> case s of+                           L -> f kA a b+                           R -> f kA b a++          | otherwise -> case s of+                           L -> safeJoin kA (oneX kA a) kB (sideY tB)+                           R -> safeJoin kA (oneY kA a) kB (sideX tB)++        Nil          -> sideA s tA++    binAny+      :: forall a b. S a b x y -> UBin a -> Patricia a -> Patricia b -> Patricia c+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Tip kB b     -> let !(# s' #) = other s+                        in tipBin s' (# kB, b #) tB uA++        Nil          -> sideA s tA++    tipBin+      :: forall a b. S a b x y -> UTip a -> Patricia a -> UBin b -> Patricia c+    tipBin s uA@(# kA, a #) tA (# pB, lB, rB #)+      | beyond pB kA = case s of+                         L -> safeJoin kA (oneX kA a) pB (treeY pB lB rB)+                         R -> safeJoin kA (oneY kA a) pB (treeX pB lB rB)++      | kA < pB      = rebin pB (tipAny s uA tA lB) (sideB s rB)++      | otherwise    = rebin pB (sideB s lB) (tipAny s uA tA rB)++    binBin+      :: forall a b. S a b x y -> UBin a -> Patricia a -> UBin b -> Patricia b -> Patricia c+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = case s of+                 L -> safeJoin pA (treeX pA lA rA) pB (treeY pB lB rB)+                 R -> safeJoin pA (treeY pA lA rA) pB (treeX pB lB rB)++      in case Prelude.compare pA pB of+           EQ                  -> rebin pA (anyAny s lA lB) (anyAny s rA rB)++           LT | pB <= upper pA -> let !(# s' #) = other s++                                  in rebin pA (sideA s lA) (binAny s' uB tB rA)++              | pA >= lower pB -> rebin pB (binAny s uA tA lB) (sideB s rB)++              | otherwise      -> no++           GT | pA <= upper pB -> rebin pB (sideB s lB) (binAny s uA tA rB)++              | pB >= lower pA -> let !(# s' #) = other s++                                  in rebin pA (binAny s' uB tB lA) (sideA s rA)++              | otherwise      -> no++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the value at a key in the tree.+lookup :: Word -> Patricia a -> Maybe a+lookup !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> Nothing+          | w < p      -> go l+          | otherwise  -> go r++        Tip k a+          | k == w    -> Just a+          | otherwise -> Nothing++        Nil -> Nothing++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the value at a key in the tree, falling back to the given default value+--   if it does not exist.+find :: a -> Word -> Patricia a -> a+find d !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> d+          | w < p      -> go l+          | otherwise  -> go r++        Tip k a+          | k == w    -> a+          | otherwise -> d++        Nil -> d++-- | \(\mathcal{O}(\min(n,W))\).+--   Check whether the value exists at a key in the tree.+member :: Word -> Patricia a -> Bool+member !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> False+          | w < p      -> go l+          | otherwise  -> go r++        Tip k _ -> k == w++        Nil -> False++-- 'lookup' that doesn't allocate a 'Maybe'.+takeOne :: Word -> Patricia a -> Patricia a+takeOne !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> Nil+          | w < p      -> go l+          | otherwise  -> go r++        Tip k _+          | k == w    -> t+          | otherwise -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, it is replaced.+insert :: Word -> a -> Patricia a -> Patricia a+insert !w a = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> join w (Tip w a) p t+          | w < p      -> Bin p (go l) r+          | otherwise  -> Bin p l (go r)++        Tip k _+          | k == w    -> Tip k a+          | otherwise -> join w (Tip w a) k t++        Nil -> Tip w a++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, the function is used instead.+insertWith :: (a -> a) -> Word -> a -> Patricia a -> Patricia a+insertWith f !w b = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> join w (Tip w b) p t+          | w < p      -> Bin p (go l) r+          | otherwise  -> Bin p l (go r)++        Tip k a+          | k == w    -> Tip k (f a)+          | otherwise -> join w (Tip w b) k t++        Nil -> Tip w b++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Apply a function to a value in the tree at the given key.+adjust :: (a -> a) -> Word -> Patricia a -> Patricia a+adjust f !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> Bin p (go l) r+          | otherwise  -> Bin p l (go r)++        Tip k a+          | k == w    -> Tip k (f a)+          | otherwise -> t++        Nil -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Delete a value in the tree at the given key.+delete :: Word -> Patricia a -> Patricia a+delete !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> rebinL p (go l) r+          | otherwise  -> rebinR p l (go r)++        Tip k _+          | k == w    -> Nil+          | otherwise -> t++        Nil -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Update or delete a value in the tree at the given key.+update :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a+update f !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> rebinL p (go l) r+          | otherwise  -> rebinR p l (go r)++        Tip k a+          | k == w    -> retip k (f a)+          | otherwise -> t++        Nil -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Insert, update or delete a value in the tree at the given key.+alter :: (Maybe a -> Maybe a) -> Word -> Patricia a -> Patricia a+alter f !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> case f Nothing of+                            Just b  -> join p t w (Tip w b)+                            Nothing -> t++          | w < p      -> rebinL p (go l) r+          | otherwise  -> rebinR p l (go r)++        Tip k a+          | k == w    -> case f (Just a) of+                           Just b  -> Tip k b+                           Nothing -> Nil++          | otherwise -> case f Nothing of+                           Just b  -> join k t w (Tip w b)+                           Nothing -> t++        Nil -> case f Nothing of+                 Just b  -> Tip w b+                 Nothing -> Nil++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at a largest key smaller than or equal to the given key.+lookupL :: Word -> Patricia a -> Maybe (Lookup a)+lookupL !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go l+                   else Nothing++            else Just $! if w <= upper p+                           then case go r of+                                  Just x  -> x+                                  Nothing -> unsafeLookupMaxWithKey l++                           else unsafeLookupMaxWithKey r++        Tip k a+          | k <= w    -> Just $! Lookup k a+          | otherwise -> Nothing++        Nil -> Nothing++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at a smallest key greater than or equal to the given key.+lookupR :: Word -> Patricia a -> Maybe (Lookup a)+lookupR !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then Just $! if w >= lower p+                           then case go l of+                                  Just x  -> x+                                  Nothing -> unsafeLookupMinWithKey r++                           else unsafeLookupMinWithKey l++            else if w <= upper p+                   then go r+                   else Nothing++        Tip k a+          | k >= w    -> Just $! Lookup k a+          | otherwise -> Nothing++        Nil -> Nothing++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   or equal to the given one.+adjustL :: (a -> a) -> Word -> Patricia a -> Patricia a+adjustL f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go l) r+                   else t++            else Bin p (Data.Patricia.Word.Lazy.Internal.map f l) $+                   if w <= upper p+                     then go r+                     else Data.Patricia.Word.Lazy.Internal.map f r++        Tip k a+          | k <= w    -> Tip k (f a)+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   or equal to the given one.+adjustLWithKey :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a+adjustLWithKey f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go l) r+                   else t++            else Bin p (mapWithKey f l) $+                   if w <= upper p+                     then go r+                     else mapWithKey f r++        Tip k a+          | k <= w    -> Tip k (f k a)+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Delete values for which keys are smaller than or equal to the given one.+deleteL :: Word -> Patricia a -> Patricia a+deleteL !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go l) r+                   else t++            else if w <= upper p+                   then go r+                   else Nil++        Tip k _+          | k <= w    -> Nil+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_L)\).+--   Update every value for which the key is smaller than or equal to the given one.+updateL :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a+updateL f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go l) r+                   else t++            else rebin p (mapMaybe f l) $+                   if w <= upper p+                     then go r+                     else mapMaybe f r++        Tip k a+          | k <= w    -> retip k (f a)+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_L)\).+--   Update every value for which the key is smaller than or equal to the given one.+updateLWithKey :: (Word -> a -> Maybe a) -> Word -> Patricia a -> Patricia a+updateLWithKey f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go l) r+                   else t++            else rebin p (mapMaybeWithKey f l) $+                   if w <= upper p+                     then go r+                     else mapMaybeWithKey f r++        Tip k a+          | k <= w    -> retip k (f k a)+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Take values for which keys are smaller than or equal to the given one.+takeL :: Word -> Patricia a -> Patricia a+takeL !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go l+                   else Nil++            else if w <= upper p+                   then rebinR p l (go r)+                   else t++        Tip k _+          | k <= w    -> t+          | otherwise -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   or equal to the given one.+adjustR :: (a -> a) -> Word -> Patricia a -> Patricia a+adjustR f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then let l' = if w >= lower p+                            then go l+                            else Data.Patricia.Word.Lazy.Internal.map f l++                 in Bin p l' (Data.Patricia.Word.Lazy.Internal.map f r)++            else if w <= upper p+                   then Bin p l (go r)+                   else t++        Tip k a+          | k >= w    -> Tip k (f a)+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   or equal to the given one.+adjustRWithKey :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a+adjustRWithKey f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then let l' = if w >= lower p+                            then go l+                            else mapWithKey f l++                 in Bin p l' (mapWithKey f r)++            else if w <= upper p+                   then Bin p l (go r)+                   else t++        Tip k a+          | k >= w    -> Tip k (f k a)+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Delete values for which keys are greater than or equal to the given one.+deleteR :: Word -> Patricia a -> Patricia a+deleteR !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go l+                   else Nil++            else if w <= upper p+                   then rebinR p l (go r)+                   else t++        Tip k _+          | k >= w    -> Nil+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_R)\).+--   Update every value for which the key is greater than or equal to the given one.+updateR :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a+updateR f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then let l' = if w >= lower p+                            then go l+                            else mapMaybe f l++                 in rebin p l' (mapMaybe f r)++            else if w <= upper p+                   then rebinR p l (go r)+                   else t++        Tip k a+          | k >= w    -> retip k (f a)+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_R)\).+--   Update every value for which the key is greater than or equal to the given one.+updateRWithKey :: (Word -> a -> Maybe a) -> Word -> Patricia a -> Patricia a+updateRWithKey f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then let l' = if w >= lower p+                            then go l+                            else mapMaybeWithKey f l++                 in rebin p l' (mapMaybeWithKey f r)++            else if w <= upper p+                   then rebinR p l (go r)+                   else t++        Tip k a+          | k >= w    -> retip k (f k a)+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Take values for which keys are greater than or equal to the given one.+takeR :: Word -> Patricia a -> Patricia a+takeR !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go l) r+                   else t++            else if w <= upper p+                   then go r+                   else Nil++        Tip k _+          | k >= w    -> t+          | otherwise -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+adjustRange :: (a -> a) -> Range -> Patricia a -> Patricia a+adjustRange f (UnsafeRange kL kR)+  | kL == kR  = adjust f kL+  | otherwise = unsafeAdjustRange f kL kR++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeAdjustRange+  :: (a -> a)+  -> Word     -- ^ \(k_L\)+  -> Word     -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeAdjustRange f !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> Bin p (adjustR f wL l) (adjustL f wR r)++            LT | pM <= upper p -> Bin p l (go r)+               | p >= lower pM -> if wL < p+                                    then Bin p+                                           (adjustR f wL l)+                                           (Data.Patricia.Word.Lazy.Internal.map f r)++                                    else Bin p l (adjustR f wL r)++               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then Bin p+                                           (Data.Patricia.Word.Lazy.Internal.map f l)+                                           (adjustL f wR r)++                                    else Bin p (adjustL f wR l) r++               | pM >= lower p -> Bin p (go l) r+               | otherwise     -> t++        Tip k a+          | k >= wL && k <= wR -> Tip k (f a)+          | otherwise          -> t++        Nil -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+adjustRangeWithKey :: (Word -> a -> a) -> Range -> Patricia a -> Patricia a+adjustRangeWithKey f (UnsafeRange kL kR)+  | kL == kR  = adjust (f kL) kL+  | otherwise = unsafeAdjustRangeWithKey f kL kR++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeAdjustRangeWithKey+  :: (Word -> a -> a)+  -> Word             -- ^ \(k_L\)+  -> Word             -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeAdjustRangeWithKey f !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> Bin p (adjustRWithKey f wL l) (adjustLWithKey f wR r)++            LT | pM <= upper p -> Bin p l (go r)+               | p >= lower pM -> if wL < p+                                    then Bin p (adjustRWithKey f wL l) (mapWithKey f r)+                                    else Bin p l (adjustRWithKey f wL r)++               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then Bin p (mapWithKey f l) (adjustLWithKey f wR r)+                                    else Bin p (adjustLWithKey f wR l) r++               | pM >= lower p -> Bin p (go l) r+               | otherwise     -> t++        Tip k a+          | k >= wL && k <= wR -> Tip k (f k a)+          | otherwise          -> t++        Nil -> Nil+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Delete values for which keys are in the given range.+deleteRange :: Range -> Patricia a -> Patricia a+deleteRange (UnsafeRange kL kR)+  | kL == kR  = delete kL+  | otherwise = unsafeDeleteRange kL kR++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Delete values for which keys are in the given range.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeDeleteRange+  :: Word         -- ^ \(k_L\)+  -> Word         -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeDeleteRange !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> rebin p (deleteR wL l) (deleteL wR r)++            LT | pM <= upper p -> rebinR p l (go r)+               | p >= lower pM -> if wL < p+                                    then deleteR wL l+                                    else rebinR p l (deleteR wL r)+               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then deleteL wR r+                                    else rebinL p (deleteL wR l) r++               | pM >= lower p -> rebinL p (go l) r+               | otherwise     -> t++        Tip k _+          | k >= wL && k <= wR -> Nil+          | otherwise          -> t++        Nil -> Nil+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_I)\).+--   Update every value for which the key is in the given range.+updateRange :: (a -> Maybe a) -> Range -> Patricia a -> Patricia a+updateRange f (UnsafeRange kL kR)+  | kL == kR  = update f kL+  | otherwise = unsafeUpdateRange f kL kR++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_I)\).+--   Update every value for which the key is in the given range.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeUpdateRange+  :: (a -> Maybe a)+  -> Word           -- ^ \(k_L\)+  -> Word           -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeUpdateRange f !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> rebin p (updateR f wL l) (updateL f wR r)++            LT | pM <= upper p -> rebinR p l (go r)+               | p >= lower pM -> if wL < p+                                    then rebinL p (updateR f wL l) (mapMaybe f r)+                                    else rebinR p l (updateR f wL r)+               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then rebinR p (mapMaybe f l) (updateL f wR r)+                                    else rebinL p (updateL f wR l) r++               | pM >= lower p -> rebinL p (go l) r+               | otherwise     -> t++        Tip k a+          | k >= wL && k <= wR -> retip k (f a)+          | otherwise          -> t++        Nil -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_I)\).+--   Update every value for which the key is in the given range.+updateRangeWithKey :: (Word -> a -> Maybe a) -> Range -> Patricia a -> Patricia a+updateRangeWithKey f (UnsafeRange kL kR)+  | kL == kR  = update (f kL) kL+  | otherwise = unsafeUpdateRangeWithKey f kL kR++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W) + n_I)\).+--   Update every value for which the key is in the given range.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeUpdateRangeWithKey+  :: (Word -> a -> Maybe a)+  -> Word                   -- ^ \(k_L\)+  -> Word                   -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeUpdateRangeWithKey f !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> rebin p (updateRWithKey f wL l) (updateLWithKey f wR r)++            LT | pM <= upper p -> rebinR p l (go r)+               | p >= lower pM -> if wL < p+                                    then rebinL p (updateRWithKey f wL l)+                                                  (mapMaybeWithKey f r)++                                    else rebinR p l (updateRWithKey f wL r)+               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then rebinR p (mapMaybeWithKey f l)+                                                  (updateLWithKey f wR r)++                                    else rebinL p (updateLWithKey f wR l) r++               | pM >= lower p -> rebinL p (go l) r+               | otherwise     -> t++        Tip k a+          | k >= wL && k <= wR -> retip k (f k a)+          | otherwise          -> t++        Nil -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Take values for which keys are in the given range.+takeRange :: Range -> Patricia a -> Patricia a+takeRange (UnsafeRange kL kR)+  | kL == kR  = takeOne kL+  | otherwise = unsafeTakeRange kL kR++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Take values for which keys are in the given range.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeTakeRange+  :: Word       -- ^ \(k_L\)+  -> Word       -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeTakeRange !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> rebin p (takeR wL l) (takeL wR r)++            LT | pM <= upper p -> go r+               | p >= lower pM -> if wL < p+                                    then rebinL p (takeR wL l) r+                                    else takeR wL r++               | otherwise     -> Nil++            GT | p <= upper pM -> if wR >= p+                                    then rebinR p l (takeL wR r)+                                    else takeL wR l++               | pM >= lower p -> go l+               | otherwise     -> Nil++        Tip k _+          | k >= wL && k <= wR -> t+          | otherwise          -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Split the tree into two, such that+--   values with keys smaller than or equal to the given one are on the left,+--   and values with keys greater than the given one are on the right.+splitL :: Word -> Patricia a -> (Patricia a, Patricia a)+splitL !w = \t ->+  case go t of+    (# l, r #) -> (l, r)+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then let !(# ll, lr #) = go l+                        in (# ll, rebinL p lr r #)++                   else (# Nil, t #)++            else if w <= upper p+                   then let !(# rl, rr #) = go r+                        in (# rebinR p l rl, rr #)++                   else (# t, Nil #)++        Tip k _+          | w >= k    -> (# t, Nil #)+          | otherwise -> (# Nil, t #)++        Nil -> (# Nil, Nil #)++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Split the tree into two, such that+--   values with keys smaller than the given one are on the left,+--   and values with keys greater than or equal to the given one are on the right.+splitR :: Word -> Patricia a -> (Patricia a, Patricia a)+splitR !w = \t ->+  case go t of+    (# l, r #) -> (l, r)+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then let (# ll, lr #) = go l+                        in (# ll, rebinL p lr r #)++                   else (# Nil, t #)++            else if w <= upper p+                   then let (# rl, rr #) = go r+                        in (# rebinR p l rl, rr #)++                   else (# t, Nil #)++        Tip k _+          | w > k     -> (# t, Nil #)+          | otherwise -> (# Nil, t #)++        Nil -> (# Nil, Nil #)++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Split the tree into two, such that+--   values with keys smaller than the given one are on the left,+--   values with keys greater than the given one are on the right,+--   and the value at the given key is returned separately.+splitLookup :: Word -> Patricia a -> (Patricia a, Maybe a, Patricia a)+splitLookup !w = \t ->+  case go t of+    (# l, mx, r #) -> (l, mx, r)+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then let !(# ll, mx, lr #) = go l+                        in (# ll, mx, rebinL p lr r #)++                   else (# Nil, Nothing, t #)++            else if w <= upper p+                   then let !(# rl, mx, rr #) = go r+                        in (# rebinR p l rl, mx, rr #)++                   else (# t, Nothing, Nil #)++        Tip k a ->+          case w `Prelude.compare` k of+            EQ -> (# Nil, Just a , Nil #)+            GT -> (# t  , Nothing, Nil #)+            LT -> (# Nil, Nothing, t   #)++        Nil -> (# Nil, Nothing, Nil #)++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filter :: (a -> Bool) -> Patricia a -> Patricia a+filter f = go+  where+    go t =+      case t of+        Bin p l r -> rebin p (go l) (go r)++        Tip _ a+          | f a       -> t+          | otherwise -> Nil++        Nil -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filterWithKey :: (Word -> a -> Bool) -> Patricia a -> Patricia a+filterWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> rebin p (go l) (go r)++        Tip k a+          | f k a     -> t+          | otherwise -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create one out of 'Just' values.+mapMaybe :: (a -> Maybe b) -> Patricia a -> Patricia b+mapMaybe f = go+  where+    go t =+      case t of+        Bin p l r -> rebin p (go l) (go r)++        Tip k a ->+          case f a of+            Just b  -> Tip k b+            Nothing -> Nil++        Nil -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree+--   and create a tree out of 'Just' results.+mapMaybeWithKey :: (Word -> a -> Maybe b) -> Patricia a -> Patricia b+mapMaybeWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> rebin p (go l) (go r)++        Tip k a ->+          case f k a of+            Just b  -> Tip k b+            Nothing -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Split the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partition :: (a -> Bool) -> Patricia a -> (Patricia a, Patricia a)+partition f = \t ->+  case go t of+    (# l, r #) -> (l, r)+  where+    go t =+      case t of+        Bin p l r ->+          let !(# ll, lr #) = go l+              !(# rl, rr #) = go r++          in (# rebin p ll rl, rebin p lr rr #)++        Tip _ a+          | f a       -> (# t, Nil #)+          | otherwise -> (# Nil, t #)++        Nil -> (# Nil, Nil #)++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Split the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partitionWithKey :: (Word -> a -> Bool) -> Patricia a -> (Patricia a, Patricia a)+partitionWithKey f = \t ->+  case go t of+    (# l, r #) -> (l, r)+  where+    go t =+      case t of+        Bin p l r ->+          let !(# ll, lr #) = go l+              !(# rl, rr #) = go r++          in (# rebin p ll rl, rebin p lr rr #)++        Tip k a+          | f k a     -> (# t, Nil #)+          | otherwise -> (# Nil, t #)++        Nil -> (# Nil, Nil #)+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+mapEither :: (a -> Either b c) -> Patricia a -> (Patricia b, Patricia c)+mapEither f = \t ->+  case go t of+    (# l, r #) -> (l, r)+  where+    go t =+      case t of+        Bin p l r ->+          let !(# ll, lr #) = go l+              !(# rl, rr #) = go r++          in (# rebin p ll rl, rebin p lr rr #)++        Tip k a ->+          case f a of+            Left b  -> (# Tip k b, Nil #)+            Right c -> (# Nil, Tip k c #)++        Nil -> (# Nil, Nil #)++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+mapEitherWithKey :: (Word -> a -> Either b c) -> Patricia a -> (Patricia b, Patricia c)+mapEitherWithKey f = \t ->+  case go t of+    (# l, r #) -> (l, r)+  where+    go t =+      case t of+        Bin p l r ->+          let !(# ll, lr #) = go l+              !(# rl, rr #) = go r++          in (# rebin p ll rl, rebin p lr rr #)++        Tip k a ->+          case f k a of+            Left b  -> (# Tip k b, Nil #)+            Right c -> (# Nil, Tip k c #)++        Nil -> (# Nil, Nil #)++++moduleLoc :: String+moduleLoc = "Patricia.Word.Lazy"++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the leftmost key in the tree.+lookupMin :: Patricia a -> Maybe a+lookupMin Nil = Nothing+lookupMin t   = let !(# a #) = unsafeLookupMin t+                in Just a++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMin :: Patricia a -> (# a #)+unsafeLookupMin t =+  case t of+    Bin _ l _ -> unsafeLookupMin l+    Tip _ a   -> (# a #)+    Nil       -> throw $ MalformedTree moduleLoc "lookupMin"+++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the leftmost key in the tree.+lookupMinWithKey :: Patricia a -> Maybe (Lookup a)+lookupMinWithKey Nil = Nothing+lookupMinWithKey t   = Just $! unsafeLookupMinWithKey t++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMinWithKey :: Patricia a -> Lookup a+unsafeLookupMinWithKey t =+  case t of+    Bin _ l _ -> unsafeLookupMinWithKey l+    Tip k a   -> Lookup k a+    Nil       -> throw $ MalformedTree moduleLoc "lookupMinWithKey"++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the rightmost key in the tree.+lookupMax :: Patricia a -> Maybe a+lookupMax Nil = Nothing+lookupMax t   = let !(# a #) = unsafeLookupMax t+                in Just a++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMax :: Patricia a -> (# a #)+unsafeLookupMax t =+  case t of+    Bin _ _ r -> unsafeLookupMax r+    Tip _ a   -> (# a #)+    Nil       -> throw $ MalformedTree moduleLoc "lookupMax"+++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the rightmost key in the tree.+lookupMaxWithKey :: Patricia a -> Maybe (Lookup a)+lookupMaxWithKey Nil = Nothing+lookupMaxWithKey t   = Just $! unsafeLookupMaxWithKey t++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMaxWithKey :: Patricia a -> Lookup a+unsafeLookupMaxWithKey t =+  case t of+    Bin _ _ r -> unsafeLookupMaxWithKey r+    Tip k a   -> Lookup k a+    Nil       -> throw $ MalformedTree moduleLoc "lookupMaxWithKey"++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Delete a value at the leftmost key in the tree.+deleteMin :: Patricia a -> Patricia a+deleteMin = go+  where+    go t =+      case t of+        Bin p l r -> rebinL p (go l) r+        _         -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Delete a value at the rightmost key in the tree.+deleteMax :: Patricia a -> Patricia a+deleteMax = go+  where+    go t =+      case t of+        Bin p l r -> rebinR p l (go r)+        _         -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Update a value at the leftmost key in the tree.+adjustMin :: (a -> a) -> Patricia a -> Patricia a+adjustMin f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) r+        Tip k a   -> Tip k (f a)+        Nil       -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Update a value at the leftmost key in the tree.+adjustMinWithKey :: (Word -> a -> a) -> Patricia a -> Patricia a+adjustMinWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) r+        Tip k a   -> Tip k (f k a)+        Nil       -> Nil+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Update a value at the rightmost key in the tree.+adjustMax :: (a -> a) -> Patricia a -> Patricia a+adjustMax f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p l (go r)+        Tip k a   -> Tip k (f a)+        Nil       -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Update a value at the rightmost key in the tree.+adjustMaxWithKey :: (Word -> a -> a) -> Patricia a -> Patricia a+adjustMaxWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p l (go r)+        Tip k a   -> Tip k (f k a)+        Nil       -> Nil++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Update or delete a value at the leftmost key in the tree.+updateMin :: (a -> Maybe a) -> Patricia a -> Patricia a+updateMin f = go+  where+    go t =+      case t of+        Bin p l r -> rebinL p (go l) r+        Tip k a   -> retip k (f a)+        Nil       -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Update or delete a value at the leftmost key in the tree.+updateMinWithKey :: (Word -> a -> Maybe a) -> Patricia a -> Patricia a+updateMinWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> rebinL p (go l) r+        Tip k a   -> retip k (f k a)+        Nil       -> Nil+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Update or delete a value at the rightmost key in the tree.+updateMax :: (a -> Maybe a) -> Patricia a -> Patricia a+updateMax f = go+  where+    go t =+      case t of+        Bin p l r -> rebinR p l (go r)+        Tip k a   -> retip k (f a)+        Nil       -> Nil++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(n,W))\).+--   Update or delete a value at the rightmost key in the tree.+updateMaxWithKey :: (Word -> a -> Maybe a) -> Patricia a -> Patricia a+updateMaxWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> rebinR p l (go r)+        Tip k a   -> retip k (f k a)+        Nil       -> Nil++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the leftmost value and return it alongside the tree without it.+minView :: Patricia a -> Maybe (ViewL a)+minView Nil = Nothing+minView t   = Just $! unsafeMinView t++-- | The leftmost value with its key and the rest of the tree.+data ViewL a = ViewL {-# UNPACK #-} !(Lookup a) !(Patricia a)+               deriving Show++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the leftmost value and return it alongside the tree without it.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeMinView :: Patricia a -> ViewL a+unsafeMinView t =+  case t of+    Bin p l r ->+      let !(ViewL a l0) = unsafeMinView l+      in ViewL a (rebinL p l0 r)++    Tip k a -> ViewL (Lookup k a) Nil++    Nil -> throw $ MalformedTree moduleLoc "minView"++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the rightmost value and return it alongside the tree without it.+maxView :: Patricia a -> Maybe (ViewR a)+maxView Nil = Nothing+maxView t   = Just $! unsafeMaxView t++-- | The rightmost value with its key and the rest of the tree.+data ViewR a = ViewR !(Patricia a) {-# UNPACK #-} !(Lookup a)+               deriving Show++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the rightmost value and return it alongside the tree without it.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeMaxView :: Patricia a -> ViewR a+unsafeMaxView t =+  case t of+    Bin p l r ->+      let !(ViewR r0 a) = unsafeMaxView r+      in ViewR (rebinR p l r0) a++    Tip k a -> ViewR Nil (Lookup k a)++    Nil -> throw $ MalformedTree moduleLoc "maxView"
+ src/Data/Patricia/Word/Lazy/TH.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE TemplateHaskellQuotes #-}++{-|+    Template Haskell helper functions.+ -}++module Data.Patricia.Word.Lazy.TH where++import           Data.Patricia.Word.Lazy.Internal++import           Language.Haskell.TH.Syntax++++-- | \(\mathcal{O}(n)\).+--   Evaluate a tree of typed expressions.+sequenceCode :: Quote m => Patricia (Code m a) -> Code m (Patricia a)+sequenceCode t =+  case t of+    Bin p l r ->+      [|| Bin+            p+            $$(sequenceCode l)+            $$(sequenceCode r)+       ||]++    Tip k a     -> [|| Tip k $$(a) ||]+    Nil         -> [|| Nil ||]
+ src/Data/Patricia/Word/Lazy/Unsafe.hs view
@@ -0,0 +1,75 @@+{-# OPTIONS_HADDOCK not-home #-}++{-|+    Data structure internals, helper operations and unsafe functions.+ -}++module Data.Patricia.Word.Lazy.Unsafe+  ( Patricia (..)++    -- ** Bit operations+  , Prefix+  , Key++    -- | === Compare+  , beyond+  , upper+  , lower++    -- | === Create+  , Mask+  , zeroBit+  , mask+  , branchingBit++    -- * Exceptions+  , MalformedTree (..)++    -- * Range #range#+  , Range (..)++    -- ** Map+  , unsafeAdjustRange+  , unsafeAdjustRangeWithKey++    -- ** Delete+  , unsafeDeleteRange++    -- ** Update+  , unsafeUpdateRange+  , unsafeUpdateRangeWithKey++    -- ** Take+  , unsafeTakeRange++    -- * Edges+    -- ** Lookup+  , Lookup (..)++    -- | === Min+  , unsafeLookupMin+  , unsafeLookupMinWithKey++    -- | === Max+  , unsafeLookupMax+  , unsafeLookupMaxWithKey++    -- ** View+    -- | === Min+  , ViewL (..)+  , unsafeMinView++    -- | === Max+  , ViewR (..)+  , unsafeMaxView++    -- * Full-tree+    -- ** Merge+  , merge+  ) where++import           Data.Patricia.Word.Common+import           Data.Patricia.Word.Lazy.Internal+import           Radix.Exception+import           Radix.Word.Common+import           Radix.Word.Foundation
+ src/Data/Patricia/Word/Strict.hs view
@@ -0,0 +1,278 @@+{-|+    @'StrictPatricia' a@ is a spine-strict big-endian PATRICIA tree, a compressed+    binary trie, using 'Word's as keys.++    == Laziness++    Evaluating the root of the tree (i.e. @(_ :: 'StrictPatricia' a)@) to+    weak head normal form evaluates the entire spine of the tree to normal form.++    Functions do not perform any additional evaluations unless+    their documentation directly specifies so.++    == Performance++    Each function's time complexity is provided in the documentation.++    \(n\) refers to the total number of entries in the tree.+    Parts of the tree are denoted using subscripts: \(n_L\) refers to the left side,+    \(n_R\) to the right side, \(n_I\) to a range (interval), and+    \(n_M\) to entries collected with the use of a 'Monoid'.++    \(W\) is the size of 'Word' in bits, i.e. @'Data.Bits.finiteBitSize' (0 :: 'Word')@.++    == Implementation++    Description of the PATRICIA tree and some of the algorithms implemented can be found+    within the following paper:++      * Chris Okasaki and Andy Gill, "/Fast Mergeable Integer Maps/",+        Workshop on ML, September 1998, pages 77-86,+        <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.37.5452>+ -}++module Data.Patricia.Word.Strict+  ( StrictPatricia+  , Patricia++    -- * Construct+  , empty+  , singleton++    -- ** Convert+  , toLazy++    -- * Single-key+    -- ** Lookup+  , Data.Patricia.Word.Strict.Internal.lookup+  , Data.Patricia.Word.Strict.Internal.find+  , member++    -- *** Dirty+    --+    -- | Dirty lookups omit intermediate checks and are thus faster for keys+    --   that are in the tree, at the cost of being slower for keys not in the tree.+  , dirtyLookup+  , dirtyFind+  , dirtyMember++    -- ** Insert+  , insert+  , insertWith+  , insertWith'++    -- ** Map+  , adjust+  , adjust'++    -- ** Delete+  , delete++    -- ** Update+  , update++  , alter++    -- ** Take+  , SplitLookup (..)+  , splitLookup++    -- * Directional+    -- ** Lookup+  , Lookup (..)+  , lookupL+  , lookupR++    -- ** Map+    -- | === Left+  , adjustL+  , adjustL'+  , adjustLWithKey+  , adjustLWithKey'++    -- | === Right+  , adjustR+  , adjustR'+  , adjustRWithKey+  , adjustRWithKey'++    -- ** Delete+  , deleteL+  , deleteR++    -- ** Update+    -- | === Left+  , updateL+  , updateLWithKey++    -- | === Right+  , updateR+  , updateRWithKey++    -- ** Take+  , Split (..)++    -- | === Left+  , takeL+  , splitL++    -- | === Right+  , takeR+  , splitR++    -- * Range+  , Range (Range)++    -- ** Map+  , adjustRange+  , adjustRange'++  , adjustRangeWithKey+  , adjustRangeWithKey'++    -- ** Delete+  , deleteRange++    -- ** Update+  , updateRange+  , updateRangeWithKey++    -- ** Take+  , takeRange++    -- * Edges++    -- ** Lookup+    -- | === Min+  , lookupMin+  , lookupMinWithKey++    -- | === Max+  , lookupMax+  , lookupMaxWithKey++    -- ** Map+    -- | === Min+  , adjustMin+  , adjustMin'+  , adjustMinWithKey+  , adjustMinWithKey'++    -- | === Max+  , adjustMax+  , adjustMax'+  , adjustMaxWithKey+  , adjustMaxWithKey'++    -- ** Delete+  , deleteMin+  , deleteMax++    -- ** Update+    -- | === Min+  , updateMin+  , updateMinWithKey++    -- | === Max+  , updateMax+  , updateMaxWithKey++    -- ** View+    -- | === Min+  , ViewL (..)+  , minView++    -- | === Max+  , ViewR (..)+  , maxView++    -- * Full tree+    -- ** Size+  , Data.Patricia.Word.Strict.Internal.null+  , size++    -- ** Map+  , Data.Patricia.Word.Strict.Internal.map+  , map'+  , mapWithKey+  , mapWithKey'++    -- ** Fold+    -- | === Left-to-right+  , Data.Patricia.Word.Strict.Internal.foldl+  , Data.Patricia.Word.Strict.Internal.foldl'+  , foldlWithKey+  , foldlWithKey'++    -- | === Right-to-left+  , Data.Patricia.Word.Strict.Internal.foldr+  , Data.Patricia.Word.Strict.Internal.foldr'+  , foldrWithKey+  , foldrWithKey'++    -- | === Monoid+  , Data.Patricia.Word.Strict.Internal.foldMap+  , foldMapWithKey++    -- ** Traverse+  , Data.Patricia.Word.Strict.Internal.traverse+  , traverseWithKey++    -- ** Filter+    -- | === One side+  , Data.Patricia.Word.Strict.Internal.filter+  , filterWithKey++  , mapMaybe+  , mapMaybeWithKey++    -- | === Both sides+  , partition+  , partitionWithKey++  , mapEither+  , mapEitherWithKey++    -- ** Comparison+  , PartialOrdering (..)+  , Data.Patricia.Word.Strict.Internal.compare++    -- ** Union+  , union+  , unionL+  , unionWith'+  , unionWithKey'++    -- ** Difference+  , difference+  , differenceWith+  , differenceWithKey++    -- ** Intersection+  , disjoint+  , intersection+  , intersectionL+  , intersectionWith'+  , intersectionWithKey'++    -- ** Merge+    -- | See 'Data.Patricia.Word.Strict.Unsafe.merge'.+  ) where++import           Data.Patricia.Word.Common+import           Data.Patricia.Word.Conversion+import           Data.Patricia.Word.Strict.Internal+import           Radix.Common+import           Radix.Word.Common++++-- | \(\mathcal{O}(1)\).+--   Empty tree.+empty :: Patricia a+empty = Nil++-- | \(\mathcal{O}(1)\).+--   Tree with a single entry.+singleton :: Word -> a -> Patricia a+singleton = Tip
+ src/Data/Patricia/Word/Strict/Debug.hs view
@@ -0,0 +1,72 @@+{-|+    Safe functions for datatype introspection.+ -}++module Data.Patricia.Word.Strict.Debug+  ( -- * Show+    showsTree++    -- * Validate+  , Validity (..)+  , Reason (..)+  , validate+  ) where++import           Data.Patricia.Word.Debug+import           Data.Patricia.Word.Strict.Internal+import           Numeric.Long+import           Radix.Word.Debug++++-- | \(\mathcal{O}(n)\).+--   Shows the internal structure of the tree.+showsTree :: (a -> ShowS) -> Patricia a -> ShowS+showsTree f = go 0+  where+    go i t =+      mappend (replicate i ' ') .+        case t of+          Bin p l r ->+            showString "Bin " . showPrefix p . showChar '\n'+                              . go (i + 2) l . showChar '\n'+                              . go (i + 2) r++          Tip k a   ->+            showString "Tip " . showLongBin k . showString " => " . f a++          Nil       -> showString "Nil"++++-- | \(\mathcal{O}(n)\).+--   Checks whether the tree is well-formed.+validate :: Patricia a -> Validity+validate t =+  case t of+    Bin p l r+      | p == 0    -> Invalid ZeroPrefix+      | otherwise ->+          case go L p l of+            Valid -> go R p r+            err   -> err++    Tip _ _ -> Valid++    Nil -> Valid+  where+    go s q x =+      case x of+        Bin p l r+          | p == 0                 -> Invalid ZeroPrefix+          | not $ validBelow q s p -> Invalid $ PrefixBelow q p+          | otherwise              ->+              case go L p l of+                Valid -> go R p r+                err   -> err++        Tip k _+          | not $ validBelow q s k -> Invalid $ KeyBelow q k+          | otherwise              -> Valid++        Nil -> Invalid $ MalformedBin q
+ src/Data/Patricia/Word/Strict/Internal.hs view
@@ -0,0 +1,3051 @@+{-# LANGUAGE BangPatterns+           , DeriveLift+           , GADTs+           , RankNTypes+           , ScopedTypeVariables+           , UnboxedTuples #-}++module Data.Patricia.Word.Strict.Internal+  ( StrictPatricia+  , Patricia (..)++  , Data.Patricia.Word.Strict.Internal.null+  , size++  , Data.Patricia.Word.Strict.Internal.map+  , map'+  , mapWithKey+  , mapWithKey'++  , Data.Patricia.Word.Strict.Internal.foldl+  , Data.Patricia.Word.Strict.Internal.foldl'+  , foldlWithKey+  , foldlWithKey'++  , Data.Patricia.Word.Strict.Internal.foldr+  , Data.Patricia.Word.Strict.Internal.foldr'+  , foldrWithKey+  , foldrWithKey'++  , Data.Patricia.Word.Strict.Internal.foldMap+  , foldMapWithKey++  , Data.Patricia.Word.Strict.Internal.traverse+  , traverseWithKey++  , union+  , unionL+  , unionWith'+  , unionWithKey'++  , difference+  , differenceWith+  , differenceWithKey++  , Data.Patricia.Word.Strict.Internal.compare++  , disjoint+  , intersection+  , intersectionL+  , intersectionWith'+  , intersectionWithKey'++  , merge++  , Data.Patricia.Word.Strict.Internal.lookup+  , Data.Patricia.Word.Strict.Internal.find+  , member+  , takeOne++  , dirtyLookup+  , dirtyFind+  , dirtyMember++  , insert+  , insertWith+  , insertWith'++  , adjust+  , adjust'++  , delete++  , update++  , alter++  , lookupL+  , lookupR++  , adjustL+  , adjustL'+  , adjustLWithKey+  , adjustLWithKey'++  , adjustR+  , adjustR'+  , adjustRWithKey+  , adjustRWithKey'++  , deleteL+  , deleteR++  , updateL+  , updateR+  , updateLWithKey+  , updateRWithKey++  , adjustRange+  , unsafeAdjustRange++  , adjustRange'+  , unsafeAdjustRange'++  , adjustRangeWithKey+  , unsafeAdjustRangeWithKey++  , adjustRangeWithKey'+  , unsafeAdjustRangeWithKey'++  , deleteRange+  , unsafeDeleteRange++  , updateRange+  , unsafeUpdateRange++  , updateRangeWithKey+  , unsafeUpdateRangeWithKey++  , takeRange+  , unsafeTakeRange++  , takeL+  , takeR++  , Split (..)+  , splitL+  , splitR++  , SplitLookup (..)+  , splitLookup++  , Data.Patricia.Word.Strict.Internal.filter+  , filterWithKey++  , mapMaybe+  , mapMaybeWithKey++  , partition+  , partitionWithKey++  , mapEither+  , mapEitherWithKey++  , lookupMin+  , lookupMinWithKey+  , lookupMax+  , lookupMaxWithKey++  , unsafeLookupMin+  , unsafeLookupMinWithKey+  , unsafeLookupMax+  , unsafeLookupMaxWithKey++  , deleteMin+  , deleteMax++  , adjustMin+  , adjustMin'+  , adjustMinWithKey+  , adjustMinWithKey'+  , adjustMax+  , adjustMax'+  , adjustMaxWithKey+  , adjustMaxWithKey'++  , updateMin+  , updateMinWithKey+  , updateMax+  , updateMaxWithKey++  , ViewL (..)+  , minView+  , unsafeMinView++  , ViewR (..)+  , maxView+  , unsafeMaxView+  ) where++import           Data.Patricia.Word.Common+import           Radix.Common+import           Radix.Exception+import           Radix.Word.Common+import           Radix.Word.Foundation++import           Control.Applicative+import           Control.DeepSeq+import           Control.Exception (throw)+import           Data.Bits+import           Data.Foldable+import           Data.Functor.Classes+import           Language.Haskell.TH.Syntax (Lift)+import           Text.Read+import           Text.Show++++-- | Convenience synonym.+type StrictPatricia = Patricia++-- | Spine-strict PATRICIA tree.+data Patricia a = Bin+                    {-# UNPACK #-} !Prefix+                    !(Patricia a)          -- ^ Masked bit is @0@.+                    !(Patricia a)          -- ^ Masked bit is @1@.++                | Tip+                    {-# UNPACK #-} !Key+                    a++                | Nil -- ^ Invariant: only allowed as the root of the tree.+                  deriving Lift++instance Show a => Show (Patricia a) where+  showsPrec = liftShowsPrec showsPrec showList++instance Show1 Patricia where+  liftShowsPrec showsPrec_ showList_ _ t =+    showListWith (liftShowsPrec showsPrec_ showList_ 0) $+      foldrWithKey (\k a -> (:) (k, a)) [] t++instance Read a => Read (Patricia a) where+  readPrec = liftReadPrec readPrec readListPrec++instance Read1 Patricia where+  liftReadPrec readPrec_ readList_ =+    fmap (Data.Foldable.foldl' (\z (k, a) -> insert k a z) Nil)+      (liftReadListPrec readPrec_ readList_)+++instance Eq a => Eq (Patricia a) where+  (==) = liftEq (==)++instance Eq1 Patricia where+  liftEq eq = go+    where+      go l r =+        case l of+          Bin p xl xr ->+            case r of+              Bin q yl yr -> p == q && go xl yl && go xr yr+              _           -> False++          Tip kA a ->+            case r of+              Tip kB b -> kA == kB && eq a b+              _        -> False++          Nil ->+            case r of+              Nil -> True+              _   -> False+++-- | Uses 'Data.Patricia.Word.Strict.map'.+instance Functor Patricia where+  fmap = Data.Patricia.Word.Strict.Internal.map++instance Foldable Patricia where+  foldl = Data.Patricia.Word.Strict.Internal.foldl+  foldr = Data.Patricia.Word.Strict.Internal.foldr+  foldMap = Data.Patricia.Word.Strict.Internal.foldMap++  foldl' = Data.Patricia.Word.Strict.Internal.foldl'+  foldr' = Data.Patricia.Word.Strict.Internal.foldr'++  null = Data.Patricia.Word.Strict.Internal.null+  length = fromIntegral . size++instance Traversable Patricia where+  traverse = Data.Patricia.Word.Strict.Internal.traverse+++instance NFData a => NFData (Patricia a) where+  rnf = liftRnf rnf++instance NFData1 Patricia where+  liftRnf nf = go+    where+      go t =+        case t of+          Bin _ l r -> go l `seq` go r+          Tip _ a   -> nf a+          Nil       -> ()++++{-# INLINE join #-}+-- | Knowing that the prefices of two non-'Nil' trees disagree, construct a 'Bin'.+join :: Prefix -> Patricia a -> Prefix -> Patricia a -> Patricia a+join p0 t0 p1 t1 =+  let m = branchingBit p0 p1++      p = mask p0 m .|. m++  in if zeroBit p0 m+       then Bin p t0 t1+       else Bin p t1 t0++{-# INLINE safeJoin #-}+-- | Knowing that the prefices of two trees disagree, construct a 'Bin'.+safeJoin :: Prefix -> Patricia a -> Prefix -> Patricia a -> Patricia a+safeJoin _  Nil _  t1  = t1+safeJoin _  t0  _  Nil = t0+safeJoin p0 t0  p1 t1  = join p0 t0 p1 t1++{-# INLINE rebin #-}+-- | Reconstruct a 'Bin' knowing that either of the sides may now be a 'Nil'.+rebin :: Prefix -> Patricia a -> Patricia a -> Patricia a+rebin p l r =+  case l of+    Nil -> r+    _   ->+      case r of+        Nil -> l+        _   -> Bin p l r++{-# INLINE rebinL #-}+-- | Reconstruct a 'Bin' knowing that the left side may now be a 'Nil'.+rebinL :: Prefix -> Patricia a -> Patricia a -> Patricia a+rebinL p l r =+  case l of+    Nil -> r+    _   -> Bin p l r+++{-# INLINE rebinR #-}+-- | Reconstruct a 'Bin' knowing that the right side may now be a 'Nil'.+rebinR :: Prefix -> Patricia a -> Patricia a -> Patricia a+rebinR p l r =+  case r of+    Nil -> l+    _   -> Bin p l r+++{-# INLINE retip #-}+-- | Reconstruct a 'Tip' knowing that the value may not be there anymore.+retip :: Key -> Maybe a -> Patricia a+retip w (Just a) = Tip w a+retip _ Nothing  = Nil++++-- | \(\mathcal{O}(1)\).+--   Check if the tree is empty.+null :: Patricia a -> Bool+null Nil = True+null _   = False++-- | \(\mathcal{O}(n)\).+--   Calculate the number of elements stored in the tree.+--   The returned number is guaranteed to be non-negative.+size :: Patricia a -> Int+size t =+  case t of+    Bin _ l r -> let !m = size l+                     !n = size r+                 in m + n++    Tip _ _   -> 1++    Nil       -> 0++++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+map :: (a -> b) -> Patricia a -> Patricia b+map f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) (go r)+        Tip k a   -> Tip k (f a)+        Nil       -> Nil++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+--+--   New values are evaluated to WHNF.+map' :: (a -> b) -> Patricia a -> Patricia b+map' f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) (go r)+        Tip k a   -> Tip k $! f a+        Nil       -> Nil++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+mapWithKey :: (Word -> a -> b) -> Patricia a -> Patricia b+mapWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) (go r)+        Tip k a   -> Tip k (f k a)+        Nil       -> Nil++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+--+--   New values are evaluated to WHNF.+mapWithKey' :: (Word -> a -> b) -> Patricia a -> Patricia b+mapWithKey' f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) (go r)+        Tip k a   -> Tip k $! f k a+        Nil       -> Nil++++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldl :: (b -> a -> b) -> b -> Patricia a -> b+foldl f = go+  where+    go z t =+      case t of+        Bin _ l r -> go (go z l) r+        Tip _ a   -> f z a+        Nil       -> z++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldlWithKey :: (b -> Word -> a -> b) -> b -> Patricia a -> b+foldlWithKey f = go+  where+    go z t =+      case t of+        Bin _ l r -> go (go z l) r+        Tip k a   -> f z k a+        Nil       -> z++++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldl' :: (b -> a -> b) -> b -> Patricia a -> b+foldl' f = go+  where+    go !z t =+      case t of+        Bin _ l r -> let !z' = go z l+                     in go z' r+        Tip _ a   -> f z a+        Nil       -> z++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldlWithKey' :: (b -> Word -> a -> b) -> b -> Patricia a -> b+foldlWithKey' f = go+  where+    go !z t =+      case t of+        Bin _ l r -> let !z' = go z l+                     in go z' r+        Tip k a   -> f z k a+        Nil       -> z++++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldr :: (a -> b -> b) -> b -> Patricia a -> b+foldr f = go+  where+    go z t =+      case t of+        Bin _ l r -> go (go z r) l+        Tip _ a   -> f a z+        Nil       -> z++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldrWithKey :: (Word -> a -> b -> b) -> b -> Patricia a -> b+foldrWithKey f = go+  where+    go z t =+      case t of+        Bin _ l r -> go (go z r) l+        Tip k a   -> f k a z+        Nil       -> z++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldr' :: (a -> b -> b) -> b -> Patricia a -> b+foldr' f = go+  where+    go !z t =+      case t of+        Bin _ l r -> let !z' = go z r+                     in go z' l+        Tip _ a   -> f a z+        Nil       -> z++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldrWithKey' :: (Word -> a -> b -> b) -> b -> Patricia a -> b+foldrWithKey' f = go+  where+    go !z t =+      case t of+        Bin _ l r -> let !z' = go z r+                     in go z' l+        Tip k a   -> f k a z+        Nil       -> z++++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMap :: Monoid m => (a -> m) -> Patricia a -> m+foldMap f = go+  where+    go t =+      case t of+        Bin _ l r -> go l <> go r+        Tip _ a   -> f a+        Nil       -> mempty++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMapWithKey :: Monoid m => (Word -> a -> m) -> Patricia a -> m+foldMapWithKey f = go+  where+    go t =+      case t of+        Bin _ l r -> go l <> go r+        Tip k a   -> f k a+        Nil       -> mempty++++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverse :: Applicative f => (a -> f b) -> Patricia a -> f (Patricia b)+traverse f = go+  where+    go t =+      case t of+        Bin p l r -> liftA2 (Bin p) (go l) (go r)+        Tip k a   -> Tip k <$> f a+        Nil       -> pure Nil++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverseWithKey :: Applicative f => (Word -> a -> f b) -> Patricia a -> f (Patricia b)+traverseWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> liftA2 (Bin p) (go l) (go r)+        Tip k a   -> Tip k <$> f k a+        Nil       -> pure Nil++++type UBin a = (# Prefix, Patricia a, Patricia a #)++type UTip a = (# Word, a #)++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Unbiased union of two trees.+union :: Patricia a -> Patricia a -> Patricia a+union = anyAny+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA -> binAny (# pA, lA, rA #) tA tB++        Tip kA _ -> tipAny kA tA tB++        Nil -> tB++    tipAny kA tA tB =+      case tB of+        Bin pB lB rB -> tipBin kA tA (# pB, lB, rB #) tB++        Tip kB _+          | kA == kB  -> tA+          | otherwise -> join kA tA kB tB++        Nil -> tA++    binAny uA tA tB =+      case tB of+        Bin pB lB rB -> binBin uA tA (# pB, lB, rB #) tB++        Tip kB _ -> tipBin kB tB uA tA++        Nil -> tA++    tipBin kA tA (# pB, lB, rB #) tB+      | beyond pB kA = join kA tA pB tB+      | kA < pB      = Bin pB (tipAny kA tA lB) rB+      | otherwise    = Bin pB lB (tipAny kA tA rB)++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = join pA tA pB tB++      in case Prelude.compare pA pB of+           EQ                  -> Bin pA (anyAny lA lB) (anyAny rA rB)++           LT | pB <= upper pA -> Bin pA lA (binAny uB tB rA)+              | pA >= lower pB -> Bin pB (binAny uA tA lB) rB+              | otherwise      -> no++           GT | pA <= upper pB -> Bin pB lB (binAny uA tA rB)+              | pB >= lower pA -> Bin pA (binAny uB tB lA) rA+              | otherwise      -> no++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Left-biased union of two trees.+unionL :: Patricia a -> Patricia a -> Patricia a+unionL =+  union_ $ \s k a b ->+    let !(# c #) = case s of+                     L -> (# a #)+                     R -> (# b #)+    in Tip k c++-- | \(\mathcal{O}(n_A + n_B)\).+--   Union of two trees with a combining function.+--+--   New values are evaluated to WHNF.+unionWith'+  :: (a -> a -> a)+  -> Patricia a+  -> Patricia a+  -> Patricia a+unionWith' f =+  union_ $ \s k a b ->+    Tip k $! case s of+               L -> f a b+               R -> f b a++-- | \(\mathcal{O}(n_A + n_B)\).+--   Union of two trees with a combining function.+--+--   New values are evaluated to WHNF.+unionWithKey'+  :: (Word -> a -> a -> a)+  -> Patricia a+  -> Patricia a+  -> Patricia a+unionWithKey' f =+  union_ $ \s k a b ->+    Tip k $! case s of+               L -> f k a b+               R -> f k b a++++{-# INLINE union_ #-}+union_+  :: (forall x y. S x y a a -> Key -> x -> y -> Patricia a)+  -> Patricia a+  -> Patricia a+  -> Patricia a+union_ f = anyAny L+  where+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Tip kA a -> tipAny s (# kA, a #) tA tB++        Nil -> tB++    tipAny s uA@(# kA, a #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #) tB++        Tip kB b+          | kA == kB  -> f s kA a b+          | otherwise -> join kA tA kB tB++        Nil -> tA++    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Tip kB b ->+          let !(# s' #) = other s+          in tipBin s' (# kB, b #) tB uA tA++        Nil -> tA++    tipBin s uA@(# kA, _ #) tA (# pB, lB, rB #) tB+      | beyond pB kA = join kA tA pB tB+      | kA < pB      = Bin pB (tipAny s uA tA lB) rB+      | otherwise    = Bin pB lB (tipAny s uA tA rB)++    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = join pA tA pB tB++      in case Prelude.compare pA pB of+           EQ                  -> Bin pA (anyAny s lA lB) (anyAny s rA rB)++           LT | pB <= upper pA -> let !(# s' #) = other s+                                  in Bin pA lA (binAny s' uB tB rA)+              | pA >= lower pB -> Bin pB (binAny s uA tA lB) rB+              | otherwise      -> no++           GT | pA <= upper pB -> Bin pB lB (binAny s uA tA rB)+              | pB >= lower pA -> let !(# s' #) = other s+                                  in Bin pA (binAny s' uB tB lA) rA+              | otherwise      -> no++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Difference of two trees.+difference :: Patricia a -> Patricia b -> Patricia a+difference =+  difference_ $ \_ _ _ _ ->+    Nil++-- | \(\mathcal{O}(n_A + n_B)\).+--   Difference of two trees with a combining function.+--+--   The 'Maybe' is evaluated to WHNF.+differenceWith+  :: (a -> b -> Maybe a)+  -> Patricia a+  -> Patricia b+  -> Patricia a+differenceWith f =+  difference_ $ \s k a b ->+    retip k $ case s of+                L -> f a b+                R -> f b a++-- | \(\mathcal{O}(n_A + n_B)\).+--   Difference of two trees with a combining function.+--+--   The 'Maybe' is evaluated to WHNF.+differenceWithKey+  :: (Word -> a -> b -> Maybe a)+  -> Patricia a+  -> Patricia b+  -> Patricia a+differenceWithKey f =+  difference_ $ \s k a b ->+    retip k $ case s of+                L -> f k a b+                R -> f k b a++++{-# INLINE difference_ #-}+difference_+  :: (forall x y. S x y a b -> Key -> x -> y -> Patricia a)+  -> Patricia a+  -> Patricia b+  -> Patricia a+difference_ (f :: forall n o. S n o x y -> Key -> n -> o -> Patricia x) = anyAny L+  where+    anyAny+      :: forall a b. S a b x y -> Patricia a -> Patricia b -> Patricia x+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Tip kA a -> tipAny s (# kA, a #) tA tB++        Nil -> case s of+                 L -> tA+                 R -> tB++    tipAny+      :: forall a b. S a b x y -> UTip a -> Patricia a -> Patricia b -> Patricia x+    tipAny s uA@(# kA, a #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #) tB++        Tip kB b+          | kA == kB  -> f s kA a b+          | otherwise -> case s of+                           L -> tA+                           R -> tB++        Nil -> case s of+                 L -> tA+                 R -> tB++    binAny+      :: forall a b. S a b x y -> UBin a -> Patricia a -> Patricia b -> Patricia x+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Tip kB b -> let !(# s' #) = other s+                    in tipBin s' (# kB, b #) tB uA tA++        Nil -> case s of+                 L -> tA+                 R -> tB++    tipBin+      :: forall a b. S a b x y -> UTip a -> Patricia a -> UBin b -> Patricia b -> Patricia x+    tipBin s uA@(# kA, _ #) tA (# pB, lB, rB #) tB+      | beyond pB kA = case s of+                         L -> tA+                         R -> tB++      | kA < pB      = case s of+                         L -> tipAny s uA tA lB+                         R -> rebinL pB (tipAny s uA tA lB) rB++      | otherwise    = case s of+                         L -> tipAny s uA tA rB+                         R -> rebinR pB lB (tipAny s uA tA rB)++    binBin+      :: forall a b. S a b x y -> UBin a -> Patricia a -> UBin b -> Patricia b -> Patricia x+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = case s of+                 L -> tA+                 R -> tB++      in case Prelude.compare pA pB of+           EQ                  -> rebin pA (anyAny s lA lB) (anyAny s rA rB)++           LT | pB <= upper pA -> case s of+                                    L -> rebinR pA lA (binAny R uB tB rA)+                                    R -> binAny L uB tB rA++              | pA >= lower pB -> case s of+                                    L -> binAny s uA tA lB+                                    R -> rebinL pB (binAny s uA tA lB) rB++              | otherwise      -> no++           GT | pA <= upper pB -> case s of+                                    L -> binAny s uA tA rB+                                    R -> rebinR pB lB (binAny s uA tA rB)++              | pB >= lower pA -> case s of+                                    L -> rebinL pA (binAny R uB tB lA) rA+                                    R -> binAny L uB tB lA++              | otherwise      -> no++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Compare two trees with respect to set inclusion,+--   using the given equality function for intersecting keys.+--   If any intersecting keys hold unequal values, the trees are 'Incomparable'.+compare :: (a -> b -> Bool) -> Patricia a -> Patricia b -> PartialOrdering+compare (f :: x -> y -> Bool) = anyAny L+  where+    anyAny+      :: forall a b. S a b x y -> Patricia a -> Patricia b -> PartialOrdering+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Tip kA a -> tipAny s (# kA, a #) tA tB++        Nil -> case tB of+                 Nil -> Equal+                 _   -> Subset++    tipAny+      :: forall a b. S a b x y -> UTip a -> Patricia a -> Patricia b -> PartialOrdering+    tipAny s uA@(# kA, a #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #)++        Tip kB b+          | kA == kB  -> let eq = case s of+                                    L -> f a b+                                    R -> f b a+                         in if eq+                              then Equal+                              else Incomparable++          | otherwise -> Incomparable++        Nil -> Superset++    binAny+      :: forall a b. S a b x y -> UBin a -> Patricia a -> Patricia b -> PartialOrdering+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Tip kB b -> let !(# s' #) = other s+                    in tipBin s' (# kB, b #) tB uA++        Nil -> Superset++    tipBin+      :: forall a b. S a b x y -> UTip a -> Patricia a -> UBin b -> PartialOrdering+    tipBin s uA@(# kA, _ #) tA (# pB, lB, rB #) =+      if beyond pB kA+        then Incomparable+        else limit s . tipAny s uA tA $ if kA < pB+                                           then lB+                                           else rB++    binBin+      :: forall a b. S a b x y -> UBin a -> Patricia a -> UBin b -> Patricia b -> PartialOrdering+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> order (anyAny s lA lB) (anyAny s rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s+                               in limit s' $ binAny s' uB tB rA++           | pA >= lower pB -> limit s $ binAny s uA tA lB++           | otherwise      -> Incomparable++        GT | pA <= upper pB -> limit s $ binAny s uA tA rB++           | pB >= lower pA -> let !(# s' #) = other s++                               in limit s' $ binAny s' uB tB lA++           | otherwise      -> Incomparable++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Determine whether two trees' key sets are disjoint.+disjoint :: Patricia a -> Patricia b -> Bool+disjoint = anyAny+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA -> binAny (# pA, lA, rA #) tA tB++        Tip kA _ -> tipAny kA tA tB++        Nil -> True++    tipAny kA tA tB =+      case tB of+        Bin pB lB rB -> tipBin kA tA (# pB, lB, rB #)++        Tip kB _ -> kA /= kB++        Nil -> True++    binAny :: forall a b. UBin a -> Patricia a -> Patricia b -> Bool+    binAny uA tA tB =+      case tB of+        Bin pB lB rB -> binBin uA tA (# pB, lB, rB #) tB++        Tip kB _ -> tipBin kB tB uA++        Nil -> True++    tipBin kA tA (# pB, lB, rB #)+      | beyond pB kA = True+      | otherwise    = tipAny kA tA $ if kA < pB+                                        then lB+                                        else rB++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> anyAny lA lB && anyAny rA rB++        LT | pB <= upper pA -> binAny uB tB rA+           | pA >= lower pB -> binAny uA tA lB+           | otherwise      -> True++        GT | pA <= upper pB -> binAny uA tA rB+           | pB >= lower pA -> binAny uB tB lA+           | otherwise      -> True++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Unbiased intersection of two trees.+intersection :: Patricia a -> Patricia a -> Patricia a+intersection = anyAny+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA -> binAny (# pA, lA, rA #) tA tB++        Tip kA _ -> tipAny kA tA tB++        Nil -> Nil++    tipAny kA tA tB =+      case tB of+        Bin pB lB rB -> tipBin kA tA (# pB, lB, rB #)++        Tip kB _+          | kA == kB  -> tA+          | otherwise -> Nil++        Nil -> Nil++    binAny uA tA tB =+      case tB of+        Bin pB lB rB -> binBin uA tA (# pB, lB, rB #) tB++        Tip kB _ -> tipBin kB tB uA++        Nil -> Nil++    tipBin kA tA (# pB, lB, rB #)+      | beyond pB kA = Nil+      | otherwise    = tipAny kA tA $ if kA < pB+                                        then lB+                                        else rB++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny lA lB) (anyAny rA rB)++        LT | pB <= upper pA -> binAny uB tB rA+           | pA >= lower pB -> binAny uA tA lB+           | otherwise      -> Nil++        GT | pA <= upper pB -> binAny uA tA rB+           | pB >= lower pA -> binAny uB tB lA+           | otherwise      -> Nil++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Left-biased intersection of two trees.+intersectionL :: Patricia a -> Patricia b -> Patricia a+intersectionL =+  intersection_ $ \s k a b ->+    let !(# c #) = case s of+                     L -> (# a #)+                     R -> (# b #)+    in Tip k c++-- | \(\mathcal{O}(n_A + n_B)\).+--   Intersection of two trees with a combining function.+--+--   New values are evaluated to WHNF.+intersectionWith'+  :: (a -> b -> c)+  -> Patricia a+  -> Patricia b+  -> Patricia c+intersectionWith' f =+  intersection_ $ \s k a b ->+    Tip k $! case s of+               L -> f a b+               R -> f b a++-- | \(\mathcal{O}(n_A + n_B)\).+--   Intersection of two trees with a combining function.+--+--   New values are evaluated to WHNF.+intersectionWithKey'+  :: (Word -> a -> b -> c)+  -> Patricia a+  -> Patricia b+  -> Patricia c+intersectionWithKey' f =+  intersection_ $ \s k a b ->+    Tip k $! case s of+               L -> f k a b+               R -> f k b a++++{-# INLINE intersection_ #-}+intersection_+  :: (forall x y. S x y a b -> Key -> x -> y -> Patricia c)+  -> Patricia a+  -> Patricia b+  -> Patricia c+intersection_ (f :: forall n o. S n o x y -> Word -> n -> o -> Patricia c) =+  anyAny L+  where+    anyAny+      :: forall a b. S a b x y -> Patricia a -> Patricia b -> Patricia c+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Tip kA a -> tipAny s (# kA, a #) tA tB++        Nil -> Nil++    tipAny+      :: forall a b. S a b x y -> UTip a -> Patricia a -> Patricia b -> Patricia c+    tipAny s uA@(# kA, a #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #)++        Tip kB b+          | kA == kB  -> f s kA a b+          | otherwise -> Nil++        Nil -> Nil++    binAny+      :: forall a b. S a b x y -> UBin a -> Patricia a -> Patricia b -> Patricia c+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Tip kB b -> let !(# s' #) = other s+                    in tipBin s' (# kB, b #) tB uA++        Nil -> Nil++    tipBin+      :: forall a b. S a b x y -> UTip a -> Patricia a -> UBin b -> Patricia c+    tipBin s uA@(# kA, _ #) tA (# pB, lB, rB #)+      | beyond pB kA = Nil+      | otherwise    = tipAny s uA tA $ if kA < pB+                                          then lB+                                          else rB++    binBin+      :: forall a b. S a b x y -> UBin a -> Patricia a -> UBin b -> Patricia b -> Patricia c+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny s lA lB) (anyAny s rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s+                               in binAny s' uB tB rA+           | pA >= lower pB -> binAny s uA tA lB+           | otherwise      -> Nil++        GT | pA <= upper pB -> binAny s uA tA rB+           | pB >= lower pA -> let !(# s' #) = other s+                               in binAny s' uB tB lA+           | otherwise      -> Nil++++{-# INLINE merge #-}+-- | \(\mathcal{O}(n_A + n_B)\).+--   General merge of two trees.+--+--   Collision and single value functions __must__ return either+--   'Tip' with the respective key, or 'Nil'.+--+--   Subtree argument functions may return any tree, however the shape of said tree+--   __must__ be compatible with the prefix passed to the function.+--+--   Resulting 'Patricia' trees in argument functions are evaluated to WHNF.+--+--   This functions inlines when all argument functions are provided.+merge+  :: (Key -> a -> b -> Patricia c)                      -- ^ Single value collision+  -> (Key -> a -> Patricia c)                           -- ^ Single left value+  -> (Prefix -> Patricia a -> Patricia a -> Patricia c) -- ^ Left subtree+  -> (Key -> b -> Patricia c)                           -- ^ Single right value+  -> (Prefix -> Patricia b -> Patricia b -> Patricia c) -- ^ Right subtree+  -> Patricia a+  -> Patricia b+  -> Patricia c+merge (f :: Key -> x -> y -> Patricia c) oneX treeX oneY treeY = anyAny L+  where+    {-# INLINE side #-}+    side one tree t =+      case t of+        Bin p l r -> tree p l r+        Tip k a   -> one k a+        Nil       -> Nil++    sideX = side oneX treeX++    sideY = side oneY treeY++    sideA :: forall a b. S a b x y -> Patricia a -> Patricia c+    sideA s tA = case s of+                   L -> sideX tA+                   R -> sideY tA++    sideB :: forall a b. S a b x y -> Patricia b -> Patricia c+    sideB s tB = case s of+                   L -> sideY tB+                   R -> sideX tB++    anyAny+      :: forall a b. S a b x y -> Patricia a -> Patricia b -> Patricia c+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Tip kA a     -> tipAny s (# kA, a #) tA tB++        Nil          -> sideB s tB++    tipAny+      :: forall a b. S a b x y -> UTip a -> Patricia a -> Patricia b -> Patricia c+    tipAny s uA@(# kA, a #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #)++        Tip kB b+          | kA == kB  -> case s of+                           L -> f kA a b+                           R -> f kA b a++          | otherwise -> case s of+                           L -> safeJoin kA (oneX kA a) kB (sideY tB)+                           R -> safeJoin kA (oneY kA a) kB (sideX tB)++        Nil          -> sideA s tA++    binAny+      :: forall a b. S a b x y -> UBin a -> Patricia a -> Patricia b -> Patricia c+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Tip kB b     -> let !(# s' #) = other s+                        in tipBin s' (# kB, b #) tB uA++        Nil          -> sideA s tA++    tipBin+      :: forall a b. S a b x y -> UTip a -> Patricia a -> UBin b -> Patricia c+    tipBin s uA@(# kA, a #) tA (# pB, lB, rB #)+      | beyond pB kA = case s of+                         L -> safeJoin kA (oneX kA a) pB (treeY pB lB rB)+                         R -> safeJoin kA (oneY kA a) pB (treeX pB lB rB)++      | kA < pB      = rebin pB (tipAny s uA tA lB) (sideB s rB)++      | otherwise    = rebin pB (sideB s lB) (tipAny s uA tA rB)++    binBin+      :: forall a b. S a b x y -> UBin a -> Patricia a -> UBin b -> Patricia b -> Patricia c+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = case s of+                 L -> safeJoin pA (treeX pA lA rA) pB (treeY pB lB rB)+                 R -> safeJoin pA (treeY pA lA rA) pB (treeX pB lB rB)++      in case Prelude.compare pA pB of+           EQ                  -> rebin pA (anyAny s lA lB) (anyAny s rA rB)++           LT | pB <= upper pA -> let !(# s' #) = other s++                                  in rebin pA (sideA s lA) (binAny s' uB tB rA)++              | pA >= lower pB -> rebin pB (binAny s uA tA lB) (sideB s rB)++              | otherwise      -> no++           GT | pA <= upper pB -> rebin pB (sideB s lB) (binAny s uA tA rB)++              | pB >= lower pA -> let !(# s' #) = other s++                                  in rebin pA (binAny s' uB tB lA) (sideA s rA)++              | otherwise      -> no++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the value at a key in the tree.+lookup :: Word -> Patricia a -> Maybe a+lookup !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> Nothing+          | w < p      -> go l+          | otherwise  -> go r++        Tip k a+          | k == w    -> Just a+          | otherwise -> Nothing++        Nil -> Nothing++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the value at a key in the tree, falling back to the given default value+--   if it does not exist.+find :: a -> Word -> Patricia a -> a+find d !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> d+          | w < p      -> go l+          | otherwise  -> go r++        Tip k a+          | k == w    -> a+          | otherwise -> d++        Nil -> d++-- | \(\mathcal{O}(\min(n,W))\).+--   Check whether the value exists at a key in the tree.+member :: Word -> Patricia a -> Bool+member !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> False+          | w < p      -> go l+          | otherwise  -> go r++        Tip k _ -> k == w++        Nil -> False++-- 'lookup' that doesn't allocate a 'Maybe'.+takeOne :: Word -> Patricia a -> Patricia a+takeOne !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> Nil+          | w < p      -> go l+          | otherwise  -> go r++        Tip k _+          | k == w    -> t+          | otherwise -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the value at a key in the tree.+dirtyLookup :: Word -> Patricia a -> Maybe a+dirtyLookup !w = go+  where+    go t =+      case t of+        Bin p l r+          | w < p     -> go l+          | otherwise -> go r++        Tip k a+          | k == w    -> Just a+          | otherwise -> Nothing++        Nil -> Nothing++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the value at a key in the tree, falling back to the default value+--   if it does not exist.+dirtyFind :: a -> Word -> Patricia a -> a+dirtyFind d !w = go+  where+    go t =+      case t of+        Bin p l r+          | w < p     -> go l+          | otherwise -> go r++        Tip k a+          | k == w    -> a+          | otherwise -> d++        Nil -> d++-- | \(\mathcal{O}(\min(n,W))\).+--   Check whether the value exists at a key in the tree.+dirtyMember :: Word -> Patricia a -> Bool+dirtyMember !w = go+  where+    go t =+      case t of+        Bin p l r+          | w < p     -> go l+          | otherwise -> go r++        Tip k _ -> k == w++        Nil -> False++++-- | \(\mathcal{O}(\min(n,W))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, it is replaced.+insert :: Word -> a -> Patricia a -> Patricia a+insert !w a = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> join w (Tip w a) p t+          | w < p      -> Bin p (go l) r+          | otherwise  -> Bin p l (go r)++        Tip k _+          | k == w    -> Tip k a+          | otherwise -> join w (Tip w a) k t++        Nil -> Tip w a++++-- | \(\mathcal{O}(\min(n,W))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, the function is used instead.+insertWith :: (a -> a) -> Word -> a -> Patricia a -> Patricia a+insertWith f !w b = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> join w (Tip w b) p t+          | w < p      -> Bin p (go l) r+          | otherwise  -> Bin p l (go r)++        Tip k a+          | k == w    -> Tip k (f a)+          | otherwise -> join w (Tip w b) k t++        Nil -> Tip w b++-- | \(\mathcal{O}(\min(n,W))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, the function is used instead.+--+--   New value is evaluted to WHNF.+insertWith' :: (a -> a) -> Word -> a -> Patricia a -> Patricia a+insertWith' f !w b = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> join w (b `seq` Tip w b) p t+          | w < p      -> Bin p (go l) r+          | otherwise  -> Bin p l (go r)++        Tip k a+          | k == w    -> Tip k $! f a+          | otherwise -> join w (b `seq` Tip w b) k t++        Nil -> Tip w b++++-- | \(\mathcal{O}(\min(n,W))\).+--   Apply a function to a value in the tree at the given key.+adjust :: (a -> a) -> Word -> Patricia a -> Patricia a+adjust f !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> Bin p (go l) r+          | otherwise  -> Bin p l (go r)++        Tip k a+          | k == w    -> Tip k (f a)+          | otherwise -> t++        Nil -> Nil++-- | \(\mathcal{O}(\min(n,W))\).+--   Apply a function to a value in the tree at the given key.+--+--   New value is evaluated to WHNF.+adjust' :: (a -> a) -> Word -> Patricia a -> Patricia a+adjust' f !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> Bin p (go l) r+          | otherwise  -> Bin p l (go r)++        Tip k a+          | k == w    -> Tip k $! f a+          | otherwise -> t++        Nil -> Nil++++-- | \(\mathcal{O}(\min(n,W))\).+--   Delete a value in the tree at the given key.+delete :: Word -> Patricia a -> Patricia a+delete !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> rebinL p (go l) r+          | otherwise  -> rebinR p l (go r)++        Tip k _+          | k == w    -> Nil+          | otherwise -> t++        Nil -> Nil++-- | \(\mathcal{O}(\min(n,W))\).+--   Update or delete a value in the tree at the given key.+--+--   The 'Maybe' is evaluated to WHNF.+update :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a+update f !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> rebinL p (go l) r+          | otherwise  -> rebinR p l (go r)++        Tip k a+          | k == w    -> retip k (f a)+          | otherwise -> t++        Nil -> Nil++++-- | \(\mathcal{O}(\min(n,W))\).+--   Insert, update or delete a value in the tree at the given key.+--+--   The resulting 'Maybe' is evaluated to WHNF.+alter :: (Maybe a -> Maybe a) -> Word -> Patricia a -> Patricia a+alter f !w = go+  where+    go t =+      case t of+        Bin p l r+          | beyond p w -> case f Nothing of+                            Just b  -> join p t w (Tip w b)+                            Nothing -> t++          | w < p      -> rebinL p (go l) r+          | otherwise  -> rebinR p l (go r)++        Tip k a+          | k == w    -> case f (Just a) of+                           Just b  -> Tip k b+                           Nothing -> Nil++          | otherwise -> case f Nothing of+                           Just b  -> join k t w (Tip w b)+                           Nothing -> t++        Nil -> case f Nothing of+                 Just b  -> Tip w b+                 Nothing -> Nil++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at a largest key smaller than or equal to the given key.+lookupL :: Word -> Patricia a -> Maybe (Lookup a)+lookupL !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go l+                   else Nothing++            else Just $! if w <= upper p+                           then case go r of+                                  Just x  -> x+                                  Nothing -> unsafeLookupMaxWithKey l++                           else unsafeLookupMaxWithKey r++        Tip k a+          | k <= w    -> Just $! Lookup k a+          | otherwise -> Nothing++        Nil -> Nothing++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at a smallest key greater than or equal to the given key.+lookupR :: Word -> Patricia a -> Maybe (Lookup a)+lookupR !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then Just $! if w >= lower p+                           then case go l of+                                  Just x  -> x+                                  Nothing -> unsafeLookupMinWithKey r++                           else unsafeLookupMinWithKey l++            else if w <= upper p+                   then go r+                   else Nothing++        Tip k a+          | k >= w    -> Just $! Lookup k a+          | otherwise -> Nothing++        Nil -> Nothing++++-- | \(\mathcal{O}(\min(n,W) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   or equal to the given one.+adjustL :: (a -> a) -> Word -> Patricia a -> Patricia a+adjustL f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go l) r+                   else t++            else Bin p (Data.Patricia.Word.Strict.Internal.map f l) $+                   if w <= upper p+                     then go r+                     else Data.Patricia.Word.Strict.Internal.map f r++        Tip k a+          | k <= w    -> Tip k (f a)+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   or equal to the given one.+--+--   New value is evaluated to WHNF.+adjustL' :: (a -> a) -> Word -> Patricia a -> Patricia a+adjustL' f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go l) r+                   else t++            else Bin p (map' f l) $+                   if w <= upper p+                     then go r+                     else map' f r++        Tip k a+          | k <= w    -> Tip k $! f a+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   or equal to the given one.+adjustLWithKey :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a+adjustLWithKey f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go l) r+                   else t++            else Bin p (mapWithKey f l) $+                   if w <= upper p+                     then go r+                     else mapWithKey f r++        Tip k a+          | k <= w    -> Tip k (f k a)+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   or equal to the given one.+--+--   New value is evaluated to WHNF.+adjustLWithKey' :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a+adjustLWithKey' f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go l) r+                   else t++            else Bin p (mapWithKey' f l) $+                   if w <= upper p+                     then go r+                     else mapWithKey' f r++        Tip k a+          | k <= w    -> Tip k $! f k a+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(\min(n,W))\).+--   Delete values for which keys are smaller than or equal to the given one.+deleteL :: Word -> Patricia a -> Patricia a+deleteL !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go l) r+                   else t++            else if w <= upper p+                   then go r+                   else Nil++        Tip k _+          | k <= w    -> Nil+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(\min(n,W) + n_L)\).+--   Update every value for which the key is smaller than or equal to the given one.+--+--   The 'Maybe' is evaluated to WHNF.+updateL :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a+updateL f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go l) r+                   else t++            else rebin p (mapMaybe f l) $+                   if w <= upper p+                     then go r+                     else mapMaybe f r++        Tip k a+          | k <= w    -> retip k (f a)+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_L)\).+--   Update every value for which the key is smaller than or equal to the given one.+--+--   The 'Maybe' is evaluated to WHNF.+updateLWithKey :: (Word -> a -> Maybe a) -> Word -> Patricia a -> Patricia a+updateLWithKey f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go l) r+                   else t++            else rebin p (mapMaybeWithKey f l) $+                   if w <= upper p+                     then go r+                     else mapMaybeWithKey f r++        Tip k a+          | k <= w    -> retip k (f k a)+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(\min(n,W))\).+--   Take values for which keys are smaller than or equal to the given one.+takeL :: Word -> Patricia a -> Patricia a+takeL !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go l+                   else Nil++            else if w <= upper p+                   then rebinR p l (go r)+                   else t++        Tip k _+          | k <= w    -> t+          | otherwise -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(\min(n,W) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   or equal to the given one.+adjustR :: (a -> a) -> Word -> Patricia a -> Patricia a+adjustR f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then let l' = if w >= lower p+                            then go l+                            else Data.Patricia.Word.Strict.Internal.map f l++                 in Bin p l' (Data.Patricia.Word.Strict.Internal.map f r)++            else if w <= upper p+                   then Bin p l (go r)+                   else t++        Tip k a+          | k >= w    -> Tip k (f a)+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   or equal to the given one.+--+--   New value is evaluated to WHNF.+adjustR' :: (a -> a) -> Word -> Patricia a -> Patricia a+adjustR' f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then let l' = if w >= lower p+                            then go l+                            else map' f l++                 in Bin p l' (map' f r)++            else if w <= upper p+                   then Bin p l (go r)+                   else t++        Tip k a+          | k >= w    -> Tip k $! f a+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   or equal to the given one.+adjustRWithKey :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a+adjustRWithKey f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then let l' = if w >= lower p+                            then go l+                            else mapWithKey f l++                 in Bin p l' (mapWithKey f r)++            else if w <= upper p+                   then Bin p l (go r)+                   else t++        Tip k a+          | k >= w    -> Tip k (f k a)+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   or equal to the given one.+--+--   New value is evaluated to WHNF.+adjustRWithKey' :: (Word -> a -> a) -> Word -> Patricia a -> Patricia a+adjustRWithKey' f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then let l' = if w >= lower p+                            then go l+                            else mapWithKey' f l++                 in Bin p l' (mapWithKey' f r)++            else if w <= upper p+                   then Bin p l (go r)+                   else t++        Tip k a+          | k >= w    -> Tip k $! f k a+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(\min(n,W))\).+--   Delete values for which keys are greater than or equal to the given one.+deleteR :: Word -> Patricia a -> Patricia a+deleteR !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go l+                   else Nil++            else if w <= upper p+                   then rebinR p l (go r)+                   else t++        Tip k _+          | k >= w    -> Nil+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(\min(n,W) + n_R)\).+--   Update every value for which the key is greater than or equal to the given one.+--+--   The 'Maybe' is evaluated to WHNF.+updateR :: (a -> Maybe a) -> Word -> Patricia a -> Patricia a+updateR f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then let l' = if w >= lower p+                            then go l+                            else mapMaybe f l++                 in rebin p l' (mapMaybe f r)++            else if w <= upper p+                   then rebinR p l (go r)+                   else t++        Tip k a+          | k >= w    -> retip k (f a)+          | otherwise -> t++        Nil         -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_R)\).+--   Update every value for which the key is greater than or equal to the given one.+--+--   The 'Maybe' is evaluated to WHNF.+updateRWithKey :: (Word -> a -> Maybe a) -> Word -> Patricia a -> Patricia a+updateRWithKey f !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then let l' = if w >= lower p+                            then go l+                            else mapMaybeWithKey f l++                 in rebin p l' (mapMaybeWithKey f r)++            else if w <= upper p+                   then rebinR p l (go r)+                   else t++        Tip k a+          | k >= w    -> retip k (f k a)+          | otherwise -> t++        Nil         -> Nil+++-- | \(\mathcal{O}(\min(n,W))\).+--   Take values for which keys are greater than or equal to the given one.+takeR :: Word -> Patricia a -> Patricia a+takeR !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go l) r+                   else t++            else if w <= upper p+                   then go r+                   else Nil++        Tip k _+          | k >= w    -> t+          | otherwise -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+adjustRange :: (a -> a) -> Range -> Patricia a -> Patricia a+adjustRange f (UnsafeRange kL kR)+  | kL == kR  = adjust f kL+  | otherwise = unsafeAdjustRange f kL kR++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeAdjustRange+  :: (a -> a)+  -> Word     -- ^ \(k_L\)+  -> Word     -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeAdjustRange f !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> Bin p (adjustR f wL l) (adjustL f wR r)++            LT | pM <= upper p -> Bin p l (go r)+               | p >= lower pM -> if wL < p+                                    then Bin p+                                           (adjustR f wL l)+                                           (Data.Patricia.Word.Strict.Internal.map f r)++                                    else Bin p l (adjustR f wL r)++               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then Bin p+                                           (Data.Patricia.Word.Strict.Internal.map f l)+                                           (adjustL f wR r)++                                    else Bin p (adjustL f wR l) r++               | pM >= lower p -> Bin p (go l) r+               | otherwise     -> t++        Tip k a+          | k >= wL && k <= wR -> Tip k (f a)+          | otherwise          -> t++        Nil -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+--+--   New value is evaluated to WHNF.+adjustRange' :: (a -> a) -> Range -> Patricia a -> Patricia a+adjustRange' f (UnsafeRange kL kR)+  | kL == kR  = adjust' f kL+  | otherwise = unsafeAdjustRange' f kL kR++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+--+--   New value is evaluated to WHNF.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeAdjustRange'+  :: (a -> a)+  -> Word     -- ^ \(k_L\)+  -> Word     -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeAdjustRange' f !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> Bin p (adjustR' f wL l) (adjustL' f wR r)++            LT | pM <= upper p -> Bin p l (go r)+               | p >= lower pM -> if wL < p+                                    then Bin p (adjustR' f wL l) (map' f r)+                                    else Bin p l (adjustR' f wL r)++               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then Bin p (map' f l) (adjustL' f wR r)+                                    else Bin p (adjustL' f wR l) r++               | pM >= lower p -> Bin p (go l) r+               | otherwise     -> t++        Tip k a+          | k >= wL && k <= wR -> Tip k $! f a+          | otherwise          -> t++        Nil -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+adjustRangeWithKey :: (Word -> a -> a) -> Range -> Patricia a -> Patricia a+adjustRangeWithKey f (UnsafeRange kL kR)+  | kL == kR  = adjust (f kL) kL+  | otherwise = unsafeAdjustRangeWithKey f kL kR++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeAdjustRangeWithKey+  :: (Word -> a -> a)+  -> Word             -- ^ \(k_L\)+  -> Word             -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeAdjustRangeWithKey f !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> Bin p (adjustRWithKey f wL l) (adjustLWithKey f wR r)++            LT | pM <= upper p -> Bin p l (go r)+               | p >= lower pM -> if wL < p+                                    then Bin p (adjustRWithKey f wL l) (mapWithKey f r)+                                    else Bin p l (adjustRWithKey f wL r)++               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then Bin p (mapWithKey f l) (adjustLWithKey f wR r)+                                    else Bin p (adjustLWithKey f wR l) r++               | pM >= lower p -> Bin p (go l) r+               | otherwise     -> t++        Tip k a+          | k >= wL && k <= wR -> Tip k (f k a)+          | otherwise          -> t++        Nil -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+--+--   New value is evaluated to WHNF.+adjustRangeWithKey' :: (Word -> a -> a) -> Range -> Patricia a -> Patricia a+adjustRangeWithKey' f (UnsafeRange kL kR)+  | kL == kR  = adjust' (f kL) kL+  | otherwise = unsafeAdjustRangeWithKey' f kL kR++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Apply a function to every value for which the key is in the given range.+--+--   New value is evaluated to WHNF.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeAdjustRangeWithKey'+  :: (Word -> a -> a)+  -> Word             -- ^ \(k_L\)+  -> Word             -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeAdjustRangeWithKey' f !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> Bin p (adjustRWithKey' f wL l) (adjustLWithKey' f wR r)++            LT | pM <= upper p -> Bin p l (go r)+               | p >= lower pM -> if wL < p+                                    then Bin p (adjustRWithKey' f wL l) (mapWithKey' f r)+                                    else Bin p l (adjustRWithKey' f wL r)++               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then Bin p (mapWithKey' f l) (adjustLWithKey' f wR r)+                                    else Bin p (adjustLWithKey' f wR l) r++               | pM >= lower p -> Bin p (go l) r+               | otherwise     -> t++        Tip k a+          | k >= wL && k <= wR -> Tip k $! f k a+          | otherwise          -> t++        Nil -> Nil+++-- | \(\mathcal{O}(\min(n,W))\).+--   Delete values for which keys are in the given range.+deleteRange :: Range -> Patricia a -> Patricia a+deleteRange (UnsafeRange kL kR)+  | kL == kR  = delete kL+  | otherwise = unsafeDeleteRange kL kR++-- | \(\mathcal{O}(\min(n,W))\).+--   Delete values for which keys are in the given range.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeDeleteRange+  :: Word         -- ^ \(k_L\)+  -> Word         -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeDeleteRange !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> rebin p (deleteR wL l) (deleteL wR r)++            LT | pM <= upper p -> rebinR p l (go r)+               | p >= lower pM -> if wL < p+                                    then deleteR wL l+                                    else rebinR p l (deleteR wL r)+               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then deleteL wR r+                                    else rebinL p (deleteL wR l) r++               | pM >= lower p -> rebinL p (go l) r+               | otherwise     -> t++        Tip k _+          | k >= wL && k <= wR -> Nil+          | otherwise          -> t++        Nil -> Nil+++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Update every value for which the key is in the given range.+--+--   The 'Maybe' is evaluated to WHNF.+updateRange :: (a -> Maybe a) -> Range -> Patricia a -> Patricia a+updateRange f (UnsafeRange kL kR)+  | kL == kR  = update f kL+  | otherwise = unsafeUpdateRange f kL kR++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Update every value for which the key is in the given range.+--+--   The 'Maybe' is evaluated to WHNF.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeUpdateRange+  :: (a -> Maybe a)+  -> Word           -- ^ \(k_L\)+  -> Word           -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeUpdateRange f !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> rebin p (updateR f wL l) (updateL f wR r)++            LT | pM <= upper p -> rebinR p l (go r)+               | p >= lower pM -> if wL < p+                                    then rebinL p (updateR f wL l) (mapMaybe f r)+                                    else rebinR p l (updateR f wL r)+               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then rebinR p (mapMaybe f l) (updateL f wR r)+                                    else rebinL p (updateL f wR l) r++               | pM >= lower p -> rebinL p (go l) r+               | otherwise     -> t++        Tip k a+          | k >= wL && k <= wR -> retip k (f a)+          | otherwise          -> t++        Nil -> Nil++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Update every value for which the key is in the given range.+--+--   The 'Maybe' is evaluated to WHNF.+updateRangeWithKey :: (Word -> a -> Maybe a) -> Range -> Patricia a -> Patricia a+updateRangeWithKey f (UnsafeRange kL kR)+  | kL == kR  = update (f kL) kL+  | otherwise = unsafeUpdateRangeWithKey f kL kR++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Update every value for which the key is in the given range.+--+--   The 'Maybe' is evaluated to WHNF.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeUpdateRangeWithKey+  :: (Word -> a -> Maybe a)+  -> Word                   -- ^ \(k_L\)+  -> Word                   -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeUpdateRangeWithKey f !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> rebin p (updateRWithKey f wL l) (updateLWithKey f wR r)++            LT | pM <= upper p -> rebinR p l (go r)+               | p >= lower pM -> if wL < p+                                    then rebinL p (updateRWithKey f wL l)+                                                  (mapMaybeWithKey f r)++                                    else rebinR p l (updateRWithKey f wL r)+               | otherwise     -> t++            GT | p <= upper pM -> if wR >= p+                                    then rebinR p (mapMaybeWithKey f l)+                                                  (updateLWithKey f wR r)++                                    else rebinL p (updateLWithKey f wR l) r++               | pM >= lower p -> rebinL p (go l) r+               | otherwise     -> t++        Tip k a+          | k >= wL && k <= wR -> retip k (f k a)+          | otherwise          -> t++        Nil -> Nil++++-- | \(\mathcal{O}(\min(n,W))\).+--   Take values for which keys are in the given range.+takeRange :: Range -> Patricia a -> Patricia a+takeRange (UnsafeRange kL kR)+  | kL == kR  = takeOne kL+  | otherwise = unsafeTakeRange kL kR++-- | \(\mathcal{O}(\min(n,W))\).+--   Take values for which keys are in the given range.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeTakeRange+  :: Word       -- ^ \(k_L\)+  -> Word       -- ^ \(k_R\)+  -> Patricia a+  -> Patricia a+unsafeTakeRange !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> rebin p (takeR wL l) (takeL wR r)++            LT | pM <= upper p -> go r+               | p >= lower pM -> if wL < p+                                    then rebinL p (takeR wL l) r+                                    else takeR wL r++               | otherwise     -> Nil++            GT | p <= upper pM -> if wR >= p+                                    then rebinR p l (takeL wR r)+                                    else takeL wR l++               | pM >= lower p -> go l+               | otherwise     -> Nil++        Tip k _+          | k >= wL && k <= wR -> t+          | otherwise          -> Nil++        Nil -> Nil++++-- | Result of a tree split.+data Split l r = Split !(Patricia l) !(Patricia r)+                 deriving Show++-- | \(\mathcal{O}(\min(n,W))\).+--   Split the tree into two, such that+--   values with keys smaller than or equal to the given one are on the left,+--   and values with keys greater than the given one are on the right.+splitL :: Word -> Patricia a -> Split a a+splitL !w = \t ->+  case go t of+    (# !l, !r #) -> Split l r+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then let !(# !ll, !lr #) = go l+                        in (# ll, rebinL p lr r #)++                   else (# Nil, t #)++            else if w <= upper p+                   then let !(# !rl, !rr #) = go r+                        in (# rebinR p l rl, rr #)++                   else (# t, Nil #)++        Tip k _+          | w >= k    -> (# t, Nil #)+          | otherwise -> (# Nil, t #)++        Nil -> (# Nil, Nil #)++-- | \(\mathcal{O}(\min(n,W))\).+--   Split the tree into two, such that+--   values with keys smaller than the given one are on the left,+--   and values with keys greater than or equal to the given one are on the right.+splitR :: Word -> Patricia a -> Split a a+splitR !w = \t ->+  case go t of+    (# !l, !r #) -> Split l r+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then let !(# !ll, !lr #) = go l+                        in (# ll, rebinL p lr r #)++                   else (# Nil, t #)++            else if w <= upper p+                   then let !(# !rl, !rr #) = go r+                        in (# rebinR p l rl, rr #)++                   else (# t, Nil #)++        Tip k _+          | w > k     -> (# t, Nil #)+          | otherwise -> (# Nil, t #)++        Nil -> (# Nil, Nil #)++++-- | Result of a tree split with a lookup.+data SplitLookup l x r = SplitLookup !(Patricia l) !(Maybe x) !(Patricia r)+                         deriving Show++-- | \(\mathcal{O}(\min(n,W))\).+--   Split the tree into two, such that+--   values with keys smaller than the given one are on the left,+--   values with keys greater than the given one are on the right,+--   and the value at the given key is returned separately.+splitLookup :: Word -> Patricia a -> SplitLookup a a a+splitLookup !w = \t ->+  case go t of+    (# !l, !mx, !r #) -> SplitLookup l mx r+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then let !(# !ll, !mx, !lr #) = go l+                        in (# ll, mx, rebinL p lr r #)++                   else (# Nil, Nothing, t #)++            else if w <= upper p+                   then let !(# !rl, !mx, !rr #) = go r+                        in (# rebinR p l rl, mx, rr #)++                   else (# t, Nothing, Nil #)++        Tip k a ->+          case w `Prelude.compare` k of+            EQ -> (# Nil, Just a , Nil #)+            GT -> (# t  , Nothing, Nil #)+            LT -> (# Nil, Nothing, t   #)++        Nil -> (# Nil, Nothing, Nil #)++++-- | \(\mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filter :: (a -> Bool) -> Patricia a -> Patricia a+filter f = go+  where+    go t =+      case t of+        Bin p l r -> rebin p (go l) (go r)++        Tip _ a+          | f a       -> t+          | otherwise -> Nil++        Nil -> Nil++-- | \(\mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filterWithKey :: (Word -> a -> Bool) -> Patricia a -> Patricia a+filterWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> rebin p (go l) (go r)++        Tip k a+          | f k a     -> t+          | otherwise -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create one out of 'Just' values.+--+--   The 'Maybe' is evaluated to WHNF.+mapMaybe :: (a -> Maybe b) -> Patricia a -> Patricia b+mapMaybe f = go+  where+    go t =+      case t of+        Bin p l r -> rebin p (go l) (go r)++        Tip k a ->+          case f a of+            Just b  -> Tip k b+            Nothing -> Nil++        Nil -> Nil++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree+--   and create a tree out of 'Just' results.+--+--   The 'Maybe' is evaluated to WHNF.+mapMaybeWithKey :: (Word -> a -> Maybe b) -> Patricia a -> Patricia b+mapMaybeWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> rebin p (go l) (go r)++        Tip k a ->+          case f k a of+            Just b  -> Tip k b+            Nothing -> Nil++        Nil -> Nil++++-- | \(\mathcal{O}(n)\).+--   Split the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partition :: (a -> Bool) -> Patricia a -> Split a a+partition f = \t ->+  case go t of+    (# !l, !r #) -> Split l r+  where+    go t =+      case t of+        Bin p l r ->+          let !(# !ll, !lr #) = go l+              !(# !rl, !rr #) = go r++          in (# rebin p ll rl, rebin p lr rr #)++        Tip _ a+          | f a       -> (# t, Nil #)+          | otherwise -> (# Nil, t #)++        Nil -> (# Nil, Nil #)++-- | \(\mathcal{O}(n)\).+--   Split the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partitionWithKey :: (Word -> a -> Bool) -> Patricia a -> Split a a+partitionWithKey f = \t ->+  case go t of+    (# !l, !r #) -> Split l r+  where+    go t =+      case t of+        Bin p l r ->+          let !(# !ll, !lr #) = go l+              !(# !rl, !rr #) = go r++          in (# rebin p ll rl, rebin p lr rr #)++        Tip k a+          | f k a     -> (# t, Nil #)+          | otherwise -> (# Nil, t #)++        Nil -> (# Nil, Nil #)+++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+--+--   The 'Either' is evaluated to WHNF.+mapEither :: (a -> Either b c) -> Patricia a -> Split b c+mapEither f = \t ->+  case go t of+    (# !l, !r #) -> Split l r+  where+    go t =+      case t of+        Bin p l r ->+          let !(# !ll, !lr #) = go l+              !(# !rl, !rr #) = go r++          in (# rebin p ll rl, rebin p lr rr #)++        Tip k a ->+          case f a of+            Left b  -> (# Tip k b, Nil #)+            Right c -> (# Nil, Tip k c #)++        Nil -> (# Nil, Nil #)++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+--+--   The 'Either' is evaluated to WHNF.+mapEitherWithKey :: (Word -> a -> Either b c) -> Patricia a -> Split b c+mapEitherWithKey f = \t ->+  case go t of+    (# !l, !r #) -> Split l r+  where+    go t =+      case t of+        Bin p l r ->+          let !(# !ll, !lr #) = go l+              !(# !rl, !rr #) = go r++          in (# rebin p ll rl, rebin p lr rr #)++        Tip k a ->+          case f k a of+            Left b  -> (# Tip k b, Nil #)+            Right c -> (# Nil, Tip k c #)++        Nil -> (# Nil, Nil #)++++moduleLoc :: String+moduleLoc = "Patricia.Word.Strict"++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the leftmost key in the tree.+lookupMin :: Patricia a -> Maybe a+lookupMin Nil = Nothing+lookupMin t   = let !(# a #) = unsafeLookupMin t+                in Just a++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMin :: Patricia a -> (# a #)+unsafeLookupMin t =+  case t of+    Bin _ l _ -> unsafeLookupMin l+    Tip _ a   -> (# a #)+    Nil       -> throw $ MalformedTree moduleLoc "lookupMin"+++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the leftmost key in the tree.+lookupMinWithKey :: Patricia a -> Maybe (Lookup a)+lookupMinWithKey Nil = Nothing+lookupMinWithKey t   = Just $! unsafeLookupMinWithKey t++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMinWithKey :: Patricia a -> Lookup a+unsafeLookupMinWithKey t =+  case t of+    Bin _ l _ -> unsafeLookupMinWithKey l+    Tip k a   -> Lookup k a+    Nil       -> throw $ MalformedTree moduleLoc "lookupMinWithKey"++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the rightmost key in the tree.+lookupMax :: Patricia a -> Maybe a+lookupMax Nil = Nothing+lookupMax t   = let !(# a #) = unsafeLookupMax t+                in Just a++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMax :: Patricia a -> (# a #)+unsafeLookupMax t =+  case t of+    Bin _ _ r -> unsafeLookupMax r+    Tip _ a   -> (# a #)+    Nil       -> throw $ MalformedTree moduleLoc "lookupMax"+++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the rightmost key in the tree.+lookupMaxWithKey :: Patricia a -> Maybe (Lookup a)+lookupMaxWithKey Nil = Nothing+lookupMaxWithKey t   = Just $! unsafeLookupMaxWithKey t++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMaxWithKey :: Patricia a -> Lookup a+unsafeLookupMaxWithKey t =+  case t of+    Bin _ _ r -> unsafeLookupMaxWithKey r+    Tip k a   -> Lookup k a+    Nil       -> throw $ MalformedTree moduleLoc "lookupMaxWithKey"++++-- | \(\mathcal{O}(\min(n,W))\).+--   Delete a value at the leftmost key in the tree.+deleteMin :: Patricia a -> Patricia a+deleteMin = go+  where+    go t =+      case t of+        Bin p l r -> rebinL p (go l) r+        _         -> Nil++-- | \(\mathcal{O}(\min(n,W))\).+--   Delete a value at the rightmost key in the tree.+deleteMax :: Patricia a -> Patricia a+deleteMax = go+  where+    go t =+      case t of+        Bin p l r -> rebinR p l (go r)+        _         -> Nil++++-- | \(\mathcal{O}(\min(n,W))\).+--   Update a value at the leftmost key in the tree.+adjustMin :: (a -> a) -> Patricia a -> Patricia a+adjustMin f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) r+        Tip k a   -> Tip k (f a)+        Nil       -> Nil++-- | \(\mathcal{O}(\min(n,W))\).+--   Update a value at the leftmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMin' :: (a -> a) -> Patricia a -> Patricia a+adjustMin' f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) r+        Tip k a   -> Tip k $! f a+        Nil       -> Nil+++-- | \(\mathcal{O}(\min(n,W))\).+--   Update a value at the leftmost key in the tree.+adjustMinWithKey :: (Word -> a -> a) -> Patricia a -> Patricia a+adjustMinWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) r+        Tip k a   -> Tip k (f k a)+        Nil       -> Nil++-- | \(\mathcal{O}(\min(n,W))\).+--   Update a value at the leftmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMinWithKey' :: (Word -> a -> a) -> Patricia a -> Patricia a+adjustMinWithKey' f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p (go l) r+        Tip k a   -> Tip k $! f k a+        Nil       -> Nil+++-- | \(\mathcal{O}(\min(n,W))\).+--   Update a value at the rightmost key in the tree.+adjustMax :: (a -> a) -> Patricia a -> Patricia a+adjustMax f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p l (go r)+        Tip k a   -> Tip k (f a)+        Nil       -> Nil++-- | \(\mathcal{O}(\min(n,W))\).+--   Update a value at the rightmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMax' :: (a -> a) -> Patricia a -> Patricia a+adjustMax' f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p l (go r)+        Tip k a   -> Tip k $! f a+        Nil       -> Nil++-- | \(\mathcal{O}(\min(n,W))\).+--   Update a value at the rightmost key in the tree.+adjustMaxWithKey :: (Word -> a -> a) -> Patricia a -> Patricia a+adjustMaxWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p l (go r)+        Tip k a   -> Tip k (f k a)+        Nil       -> Nil++-- | \(\mathcal{O}(\min(n,W))\).+--   Update a value at the rightmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMaxWithKey' :: (Word -> a -> a) -> Patricia a -> Patricia a+adjustMaxWithKey' f = go+  where+    go t =+      case t of+        Bin p l r -> Bin p l (go r)+        Tip k a   -> Tip k $! f k a+        Nil       -> Nil++++-- | \(\mathcal{O}(\min(n,W))\).+--   Update or delete a value at the leftmost key in the tree.+--+--   The 'Maybe' is evaluated to WHNF.+updateMin :: (a -> Maybe a) -> Patricia a -> Patricia a+updateMin f = go+  where+    go t =+      case t of+        Bin p l r -> rebinL p (go l) r+        Tip k a   -> retip k (f a)+        Nil       -> Nil++-- | \(\mathcal{O}(\min(n,W))\).+--   Update or delete a value at the leftmost key in the tree.+--+--   The 'Maybe' is evaluated to WHNF.+updateMinWithKey :: (Word -> a -> Maybe a) -> Patricia a -> Patricia a+updateMinWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> rebinL p (go l) r+        Tip k a   -> retip k (f k a)+        Nil       -> Nil+++-- | \(\mathcal{O}(\min(n,W))\).+--   Update or delete a value at the rightmost key in the tree.+--+--   The 'Maybe' is evaluated to WHNF.+updateMax :: (a -> Maybe a) -> Patricia a -> Patricia a+updateMax f = go+  where+    go t =+      case t of+        Bin p l r -> rebinR p l (go r)+        Tip k a   -> retip k (f a)+        Nil       -> Nil++-- | \(\mathcal{O}(\min(n,W))\).+--   Update or delete a value at the rightmost key in the tree.+--+--   The 'Maybe' is evaluated to WHNF.+updateMaxWithKey :: (Word -> a -> Maybe a) -> Patricia a -> Patricia a+updateMaxWithKey f = go+  where+    go t =+      case t of+        Bin p l r -> rebinR p l (go r)+        Tip k a   -> retip k (f k a)+        Nil       -> Nil++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the leftmost value and return it alongside the tree without it.+minView :: Patricia a -> Maybe (ViewL a)+minView Nil = Nothing+minView t   = Just $! unsafeMinView t++-- | The leftmost value with its key and the rest of the tree.+data ViewL a = ViewL {-# UNPACK #-} !(Lookup a) !(Patricia a)+               deriving Show++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the leftmost value and return it alongside the tree without it.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeMinView :: Patricia a -> ViewL a+unsafeMinView t =+  case t of+    Bin p l r ->+      let !(ViewL a l0) = unsafeMinView l+      in ViewL a (rebinL p l0 r)++    Tip k a -> ViewL (Lookup k a) Nil++    Nil -> throw $ MalformedTree moduleLoc "minView"++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the rightmost value and return it alongside the tree without it.+maxView :: Patricia a -> Maybe (ViewR a)+maxView Nil = Nothing+maxView t   = Just $! unsafeMaxView t++-- | The rightmost value with its key and the rest of the tree.+data ViewR a = ViewR !(Patricia a) {-# UNPACK #-} !(Lookup a)+               deriving Show++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the rightmost value and return it alongside the tree without it.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeMaxView :: Patricia a -> ViewR a+unsafeMaxView t =+  case t of+    Bin p l r ->+      let !(ViewR r0 a) = unsafeMaxView r+      in ViewR (rebinR p l r0) a++    Tip k a -> ViewR Nil (Lookup k a)++    Nil -> throw $ MalformedTree moduleLoc "maxView"
+ src/Data/Patricia/Word/Strict/TH.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE TemplateHaskellQuotes #-}++{-|+    Template Haskell helper functions.+ -}++module Data.Patricia.Word.Strict.TH where++import           Data.Patricia.Word.Strict.Internal++import           Language.Haskell.TH.Syntax++++-- | \(\mathcal{O}(n)\).+--   Evaluate a tree of typed expressions.+sequenceCode :: Quote m => Patricia (Code m a) -> Code m (Patricia a)+sequenceCode t =+  case t of+    Bin p l r ->+      [|| Bin+            p+            $$(sequenceCode l)+            $$(sequenceCode r)+       ||]++    Tip k a     -> [|| Tip k $$(a) ||]+    Nil         -> [|| Nil ||]
+ src/Data/Patricia/Word/Strict/Unsafe.hs view
@@ -0,0 +1,78 @@+{-# OPTIONS_HADDOCK not-home #-}++{-|+    Data structure internals, helper operations and unsafe functions.+ -}++module Data.Patricia.Word.Strict.Unsafe+  ( Patricia (..)++    -- * Bit operations+  , Prefix+  , Key++    -- | === Compare+  , beyond+  , upper+  , lower++    -- | === Create+  , Mask+  , zeroBit+  , mask+  , branchingBit++    -- * Exceptions+  , MalformedTree (..)++    -- * Range #range#+  , Range (..)++    -- ** Map+  , unsafeAdjustRange+  , unsafeAdjustRange'++  , unsafeAdjustRangeWithKey+  , unsafeAdjustRangeWithKey'++    -- ** Delete+  , unsafeDeleteRange++    -- ** Update+  , unsafeUpdateRange+  , unsafeUpdateRangeWithKey++    -- ** Take+  , unsafeTakeRange++    -- * Edges+    -- ** Lookup+  , Lookup (..)++    -- | === Min+  , unsafeLookupMin+  , unsafeLookupMinWithKey++    -- | === Max+  , unsafeLookupMax+  , unsafeLookupMaxWithKey++    -- ** View+    -- | === Min+  , ViewL (..)+  , unsafeMinView++    -- | === Max+  , ViewR (..)+  , unsafeMaxView++    -- * Full-tree+    -- ** Merge+  , merge+  ) where++import           Data.Patricia.Word.Common+import           Data.Patricia.Word.Strict.Internal+import           Radix.Exception+import           Radix.Word.Common+import           Radix.Word.Foundation
+ src/Data/Radix1Tree/Word8/Key.hs view
@@ -0,0 +1,58 @@+{-|+    Safe functions for building and destroying non-empty radix tree keys.+ -}++module Data.Radix1Tree.Word8.Key+  ( -- * Build+    Build1++    -- ** Raw+  , buildBytes++    -- ** ByteString+  , buildByteString+  , buildShortByteString++    -- ** Text+    -- | See "Data.Radix1Tree.Word8.Key.Unsafe#g:build.text".++    -- * Feed+  , Feed1++    -- ** Raw+  , feedBytes++    -- ** ByteString+    -- | See "Data.Radix1Tree.Word8.Key.Unsafe#g:feed.bytestring".++    -- ** Text+    -- | See "Data.Radix1Tree.Word8.Key.Unsafe#g:feed.text".+  ) where++import           Data.RadixNTree.Word8.Key++import qualified Data.ByteString as Strict (ByteString)+import           Data.ByteString.Short (ShortByteString)+import           Data.List.NonEmpty (NonEmpty)+import           Data.Word++++-- | Convert the key into a non-empty list of bytes.+buildBytes :: Build1 -> NonEmpty Word8+buildBytes = buildBytes1++-- | Convert the key into a non-empty strict 'Strict.ByteString'.+buildByteString :: Build1 -> Strict.ByteString+buildByteString = buildByteString1++-- | Convert the key into a non-empty 'ShortByteString'.+buildShortByteString :: Build1 -> ShortByteString+buildShortByteString = buildShortByteString1++++{-# INLINE feedBytes #-}+-- | Convert the non-empty list of bytes into a key.+feedBytes :: NonEmpty Word8 -> Feed1+feedBytes = feedBytes1
+ src/Data/Radix1Tree/Word8/Key/Unsafe.hs view
@@ -0,0 +1,88 @@+{-# OPTIONS_HADDOCK not-home #-}++{-|+    Non-empty radix tree key internals,+    and unsafe functions for building and destroying them.+ -}++module Data.Radix1Tree.Word8.Key.Unsafe+  ( -- * Build+    Build1 (..)+  , YtpmeNon (..)+  , Tsil (..)++    -- ** Text #build.text#+  , unsafeBuildText++    -- * Feed+  , Feed1 (..)+  , Step (..)++    -- ** ByteString #feed.bytestring#+  , unsafeFeedByteString+  , unsafeFeedShortByteString+  , unsafeFeedLazyByteString++    -- ** Text #feed.text#+  , unsafeFeedText+  , unsafeFeedLazyText+  ) where++import           Data.ByteArray.NonEmpty (Step (..))+import           Data.RadixNTree.Word8.Key++import qualified Data.ByteString as Strict (ByteString)+import qualified Data.ByteString.Lazy as Lazy (ByteString)+import           Data.ByteString.Short (ShortByteString)+import qualified Data.Text as Strict (Text)+import qualified Data.Text.Lazy as Lazy (Text)++++-- | Convert a key into a non-empty strict 'Strict.Text'.+--+--   No checks are made to ensure the resulting value is a valid sequence+--   of UTF-8 code units.+unsafeBuildText :: Build1 -> Strict.Text+unsafeBuildText = unsafeBuildText1++++{-# INLINE unsafeFeedByteString #-}+-- | Convert a strict 'Strict.ByteString' into a key.+--+--   The 'Strict.ByteString' is assumed to be non-empty.+unsafeFeedByteString :: Strict.ByteString -> Feed1+unsafeFeedByteString = unsafeFeedByteString1++{-# INLINE unsafeFeedShortByteString #-}+-- | Convert a 'ShortByteString' into a key.+--+--   The 'ShortByteString' is assumed to be non-empty.+unsafeFeedShortByteString :: ShortByteString -> Feed1+unsafeFeedShortByteString = unsafeFeedShortByteString1++{-# INLINE unsafeFeedLazyByteString #-}+-- | Convert a lazy 'Lazy.ByteString', in the form of the first chunk plus the rest,+--   into a key.+--+--   The first chunk is assumed to be non-empty.+unsafeFeedLazyByteString :: Strict.ByteString -> Lazy.ByteString -> Feed1+unsafeFeedLazyByteString = unsafeFeedLazyByteString1++++{-# INLINE unsafeFeedText #-}+-- | Convert a strict 'Strict.Text' into a key.+--+--   The 'Strict.Text' is assumed to be non-empty.+unsafeFeedText :: Strict.Text -> Feed1+unsafeFeedText = unsafeFeedText1++{-# INLINE unsafeFeedLazyText #-}+-- | Convert a lazy 'Lazy.Text', in the form of the first chunk plus the rest,+--   into a key.+--+--   The first chunk is assumed to be non-empty.+unsafeFeedLazyText :: Strict.Text -> Lazy.Text -> Feed1+unsafeFeedLazyText = unsafeFeedLazyText1
+ src/Data/Radix1Tree/Word8/Lazy.hs view
@@ -0,0 +1,791 @@+{-|+    @'LazyRadix1Tree' a@ is a spine-lazy radix tree that uses byte-aligned+    non-empty byte sequences as keys.++    == Laziness++    Evaluating any particular entry in the tree to WHNF forces the evaluation+    of the part of the spine leading up to that entry to normal form.++    == Performance++    Each function's time complexity is provided in the documentation.++    Laziness-amortized functions specify two time complexities:+    time to construct the return value (denoted with a \(\texttt{+}\)) and time to+    fully apply the function to the tree.++    \(x\) is the length of the input key.++    \(k\) is the length of the longest key stored in the tree.++    \(n\) refers to the total number of entries in the tree.+    Parts of the tree are denoted using subscripts: \(n_L\) refers to the left side,+    \(n_R\) to the right side, and \(n_M\) to entries collected with the use of a 'Monoid'.++    == Inlining++    Functions that produce and consume 'Feed1's are treated specially within the library,+    as when combined they can be reduced in a manner similar to the+    [destroy/unfoldr elimination rule](https://wiki.haskell.org/Correctness_of_short_cut_fusion#destroy.2Funfoldr).++    The elimination in this library is achieved by inlining both types of functions+    heavily. To avoid unnecessary code duplication during compilation consider creating+    helper functions that apply these functions one to another, e.g.++    @updateBS f bs = 'update' f ('Data.Radix1Tree.Word8.Key.Unsafe.unsafeFeedByteString' bs)@++    N.B. To inline properly functions that consume 'Feed1's must mention all of the+         arguments except for the tree.++    == Implementation++    See the implementation section in "Data.RadixTree.Word8.Strict.Unsafe"+    for the explanation of the innerworkings.++    See the implementation section in "Data.Patricia.Word.Strict" for literary references.+ -}++module Data.Radix1Tree.Word8.Lazy+  ( LazyRadix1Tree+  , Radix1Tree++  , RadixTree (..)++    -- * Key+  , module Data.Radix1Tree.Word8.Key++    -- * Construct+  , empty+  , singleton++    -- ** Convert+  , toStrict++    -- * Single-key+    -- ** Lookup+  , Data.Radix1Tree.Word8.Lazy.lookup+  , Data.Radix1Tree.Word8.Lazy.find+  , Data.Radix1Tree.Word8.Lazy.member+  , subtree++    -- *** Chunked+    --+    -- | Chunked lookup allows providing the key piece by piece while retaining+    --   the ability to check for early failure.+    --+    --   Note that while 'subtree' can be used to achieve the same result,+    --   it is more expensive allocation-wise, as it must ensure that+    --   the resulting tree is well-formed after each chunk application.+  , Cursor+  , cursor+  , move+  , stop+  , Location (..)+  , locate++    -- ** Insert+  , insert+  , insertWith++    -- ** Map+  , adjust++    -- ** Delete+  , delete+  , prune++    -- ** Update+  , update+  , alter+  , shape++    -- ** Take+  , splitLookup++    -- * Directional+  , Openness (..)++    -- ** Lookup+  , Lookup (..)+  , lookupL+  , lookupR++    -- ** Map+    -- | === Left+  , adjustL+  , adjustLWithKey++    -- | === Right+  , adjustR+  , adjustRWithKey++    -- ** Update+    -- | === Left+  , updateL+  , updateLWithKey++    -- | === Right+  , updateR+  , updateRWithKey++    -- ** Take+    -- | === Left+  , takeL+  , splitL++    -- | === Right+  , takeR++    -- * Edges++    -- ** Lookup+    -- | === Min+  , lookupMin+  , lookupMinWithKey++    -- | === Max+  , lookupMax+  , lookupMaxWithKey++    -- ** Map+    -- | === Min+  , adjustMin+  , adjustMinWithKey++    -- | === Max+  , adjustMax+  , adjustMaxWithKey++    -- ** Delete+  , deleteMin+  , deleteMax++    -- ** Update+    -- | === Min+  , updateMin+  , updateMinWithKey++    -- | === Max+  , updateMax+  , updateMaxWithKey++    -- ** View+    -- | === Min+  , ViewL (..)+  , minView++    -- | === Max+  , ViewR (..)+  , maxView++    -- * Full tree+    -- ** Size+  , Data.Radix1Tree.Word8.Lazy.null+  , size++    -- ** Extend+  , prefix++    -- ** Map+  , Data.Radix1Tree.Word8.Lazy.map+  , mapWithKey++    -- ** Fold+    -- | === Left-to-right+  , Data.Radix1Tree.Word8.Lazy.foldl+  , Data.Radix1Tree.Word8.Lazy.foldl'+  , foldlWithKey+  , foldlWithKey'++    -- | === Right-to-left+  , Data.Radix1Tree.Word8.Lazy.foldr+  , Data.Radix1Tree.Word8.Lazy.foldr'+  , foldrWithKey+  , foldrWithKey'++    -- | === Monoid+  , Data.Radix1Tree.Word8.Lazy.foldMap+  , foldMapWithKey++    -- ** Traverse+  , Data.Radix1Tree.Word8.Lazy.traverse+  , traverseWithKey++    -- ** Filter+    -- | === One side+  , Data.Radix1Tree.Word8.Lazy.filter+  , filterWithKey++  , mapMaybe+  , mapMaybeWithKey++    -- | === Both sides+  , partition+  , partitionWithKey++  , mapEither+  , mapEitherWithKey++    -- ** Comparison+  , PartialOrdering (..)+  , Data.Radix1Tree.Word8.Lazy.compare++    -- ** Union+  , union+  , unionL+  , unionWith+  , unionWithKey++    -- ** Difference+  , difference+  , differenceWith+  , differenceWithKey++    -- ** Intersection+  , disjoint+  , intersection+  , intersectionL+  , intersectionWith+  , intersectionWithKey++    -- ** Merge+    -- | See 'Data.Radix1Tree.Word8.Lazy.Unsafe.merge'.+  ) where++import           Data.Radix1Tree.Word8.Key+import           Data.RadixNTree.Word8.Common+import           Data.RadixNTree.Word8.Conversion+import           Data.RadixNTree.Word8.Lazy+import           Radix.Common++++-- | \(\mathcal{O}(1)\).+--   Empty tree.+empty :: Radix1Tree a+empty = empty1++{-# INLINE singleton #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(x)\).+--   Tree with a single entry.+singleton :: Feed1 -> a -> Radix1Tree a+singleton = singleton1+++-- | \(\mathcal{O}(n)\).+--   Create a strict 'Strict.Patricia' tree from a lazy one.+--+--   The resulting tree does not share its data representation with the original.+toStrict :: LazyRadix1Tree a -> StrictRadix1Tree a+toStrict = toStrict1++++-- | \(\mathcal{O}(1)\).+--   Check if the tree is empty.+null :: Radix1Tree a -> Bool+null = null1++-- | \(\mathcal{O}(n)\).+--   Calculate the number of elements stored in the tree.+--   The returned number is guaranteed to be non-negative.+size :: Radix1Tree a -> Int+size = size1++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree.+map :: (a -> b) -> Radix1Tree a -> Radix1Tree b+map = map1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree.+mapWithKey :: (Build1 -> a -> b) -> Radix1Tree a -> Radix1Tree b+mapWithKey = mapWithKey1++++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldl :: (b -> a -> b) -> b -> Radix1Tree a -> b+foldl = Data.RadixNTree.Word8.Lazy.foldl1++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldlWithKey :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey = foldlWithKey1++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldl' :: (b -> a -> b) -> b -> Radix1Tree a -> b+foldl' = foldl1'++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldlWithKey' :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey' = foldlWithKey1'++++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldr :: (a -> b -> b) -> b -> Radix1Tree a -> b+foldr = Data.RadixNTree.Word8.Lazy.foldr1++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldrWithKey :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey = foldrWithKey1++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldr' :: (a -> b -> b) -> b -> Radix1Tree a -> b+foldr' = foldr1'++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldrWithKey' :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey' = foldrWithKey1'++++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMap :: Monoid m => (a -> m) -> Radix1Tree a -> m+foldMap = foldMap1++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMapWithKey :: Monoid m => (Build1 -> a -> m) -> Radix1Tree a -> m+foldMapWithKey = foldMapWithKey1++++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverse :: Applicative f => (a -> f b) -> Radix1Tree a -> f (Radix1Tree b)+traverse = traverse1++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverseWithKey+  :: Applicative f => (Build1 -> a -> f b) -> Radix1Tree a -> f (Radix1Tree b)+traverseWithKey = traverseWithKey1++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filter :: (a -> Bool) -> Radix1Tree a -> Radix1Tree a+filter = filter1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filterWithKey :: (Build1 -> a -> Bool) -> Radix1Tree a -> Radix1Tree a+filterWithKey = filterWithKey1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create one out of 'Just' values.+mapMaybe :: (a -> Maybe b) -> Radix1Tree a -> Radix1Tree b+mapMaybe = mapMaybe1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create one out of 'Just' values.+mapMaybeWithKey :: (Build1 -> a -> Maybe b) -> Radix1Tree a -> Radix1Tree b+mapMaybeWithKey = mapMaybeWithKey1+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Split the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partition :: (a -> Bool) -> Radix1Tree a -> (Radix1Tree a, Radix1Tree a)+partition = partition1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Split the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partitionWithKey :: (Build1 -> a -> Bool) -> Radix1Tree a -> (Radix1Tree a, Radix1Tree a)+partitionWithKey = partitionWithKey1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+mapEither :: (a -> Either b c) -> Radix1Tree a -> (Radix1Tree b, Radix1Tree c)+mapEither = mapEither1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+mapEitherWithKey :: (Build1 -> a -> Either b c) -> Radix1Tree a -> (Radix1Tree b, Radix1Tree c)+mapEitherWithKey = mapEitherWithKey1++++{-# INLINE lookup #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the value at a key in the tree.+lookup :: Feed1 -> Radix1Tree a -> Maybe a+lookup = lookup1++{-# INLINE find #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the value at a key in the tree, falling back to the given default value+--   if it does not exist.+find :: a -> Feed1 -> Radix1Tree a -> a+find = find1++{-# INLINE member #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Check whether the value exists at a key in the tree.+member :: Feed1 -> Radix1Tree a -> Bool+member = member1++{-# INLINE subtree #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the part of the tree below the given prefix.+subtree :: Feed1 -> Radix1Tree a -> RadixTree a+subtree = subtree1++{-# INLINE prefix #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(x)\).+--   Prefix the root of the tree with the given key.+prefix :: Feed1 -> RadixTree a -> Radix1Tree a+prefix = prefix1+++-- | \(\mathcal{O}(1)\).+--   Make a cursor that points to the root of the tree.+cursor :: Radix1Tree a -> Cursor a+cursor = cursor1++{-# INLINE move #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Move the cursor down by the extent of the given key.+move :: Feed1 -> Cursor a -> Cursor a+move = move1++++{-# INLINE insert #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, it is replaced.+insert :: Feed1 -> a -> Radix1Tree a -> Radix1Tree a+insert = insert1++{-# INLINE insertWith #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, the function is used instead.+insertWith :: (a -> a) -> Feed1 -> a -> Radix1Tree a -> Radix1Tree a+insertWith = insertWith1+++{-# INLINE adjust #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Apply a function to a value in the tree at the given key.+adjust :: (a -> a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjust = adjust1+++{-# INLINE delete #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Delete a value in the tree at the given key.+delete :: Feed1 -> Radix1Tree a -> Radix1Tree a+delete = delete1++{-# INLINE prune #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Delete values in the tree below the given key.+prune :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+prune = prune1+++{-# INLINE update #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Update or delete a value in the tree at the given key.+update :: (a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+update = update1+++{-# INLINE alter #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Insert, update or delete a value in the tree at the given key.+alter :: (Maybe a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+alter = alter1+++{-# INLINE shape #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Update the part of the tree at the given prefix.+shape :: (RadixTree a -> RadixTree a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+shape = shape1+++{-# INLINE splitLookup #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Split the tree into two, such that+--   values with keys smaller than the given one are on the left,+--   values with keys greater than the given one are on the right,+--   and the value at the given key is returned separately.+splitLookup :: Feed1 -> Radix1Tree a -> (Radix1Tree a, Maybe a, Radix1Tree a)+splitLookup = splitLookup1++++{-# INLINE lookupL #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up a value at a largest key smaller than (or equal to) the given key.+lookupL :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)+lookupL = lookupL1+++{-# INLINE lookupR #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up a value at a smallest key greater than (or equal to) the given key.+lookupR :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)+lookupR = lookupR1++++{-# INLINE adjustL #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+adjustL :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustL = adjustL1++{-# INLINE adjustLWithKey #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+adjustLWithKey :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustLWithKey = adjustLWithKey1++++{-# INLINE adjustR #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+adjustR :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustR = adjustR1++{-# INLINE adjustRWithKey #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+adjustRWithKey :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustRWithKey = adjustRWithKey1++++{-# INLINE updateL #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_L)\).+--   Update every value for which the key is smaller than (or equal to) the given one.+updateL :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateL = updateL1++{-# INLINE updateLWithKey #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_L)\).+--   Update every value for which the key is smaller than (or equal to) the given one.+updateLWithKey :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateLWithKey = updateLWithKey1++{-# INLINE updateR #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_R)\).+--   Update every value for which the key is greater than (or equal to) the given one.+updateR :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateR = updateR1++{-# INLINE updateRWithKey #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_R)\).+--   Update every value for which the key is greater than (or equal to) the given one.+updateRWithKey :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateRWithKey = updateRWithKey1++++{-# INLINE takeL #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Take values for which keys are smaller than (or equal to) the given one.+takeL :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+takeL = takeL1++{-# INLINE takeR #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Take values for which keys are greater than (or equal to) the given one.+takeR :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+takeR = takeR1++++{-# INLINE splitL #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Split the tree into two, such that+--   values with keys smaller than (or equal to) the given one are on the left,+--   and the rest are on the right.+splitL :: Openness -> Feed1 -> Radix1Tree a -> (Radix1Tree a, Radix1Tree a)+splitL = splitL1++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+lookupMin :: Radix1Tree a -> Maybe a+lookupMin = lookupMin1++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+lookupMinWithKey :: Radix1Tree a -> Maybe (Lookup1 a)+lookupMinWithKey = lookupMinWithKey1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Delete a value at the leftmost key in the tree.+deleteMin :: Radix1Tree a -> Radix1Tree a+deleteMin = deleteMin1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+adjustMin :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMin = adjustMin1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+adjustMinWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMinWithKey = adjustMinWithKey1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+updateMin :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMin = updateMin1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+updateMinWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMinWithKey = updateMinWithKey1++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the leftmost value and return it alongside the tree without it.+minView :: Radix1Tree a -> Maybe (ViewL1 a)+minView = minView1++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+lookupMax :: Radix1Tree a -> Maybe a+lookupMax = lookupMax1++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+lookupMaxWithKey :: Radix1Tree a -> Maybe (Lookup1 a)+lookupMaxWithKey = lookupMaxWithKey1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Delete a value at the rightmost key in the tree.+deleteMax :: Radix1Tree a -> Radix1Tree a+deleteMax = deleteMax1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+adjustMax :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMax = adjustMax1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+adjustMaxWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMaxWithKey = adjustMaxWithKey1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+updateMax :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMax = updateMax1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+updateMaxWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMaxWithKey = updateMaxWithKey1++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the rightmost value and return it alongside the tree without it.+maxView :: Radix1Tree a -> Maybe (ViewR1 a)+maxView = maxView1++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Unbiased union of two trees.+union :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+union = union1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Left-biased union of two trees.+unionL :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionL = unionL1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Union of two trees with a combining function.+unionWith :: (a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionWith = unionWith1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Union of two trees with a combining function.+unionWithKey :: (Build1 -> a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionWithKey = unionWithKey1++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees.+difference :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a+difference = difference1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees with a combining function.+differenceWith :: (a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a+differenceWith = differenceWith1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees with a combining function.+differenceWithKey+  :: (Build1 -> a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a+differenceWithKey = differenceWithKey1++++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Compare two trees with respect to set inclusion,+--   using the given equality function for intersecting keys.+--   If any intersecting keys hold unequal values, the trees are 'Incomparable'.+compare :: (a -> b -> Bool) -> Radix1Tree a -> Radix1Tree b -> PartialOrdering+compare = compare1++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Determine whether two trees' key sets are disjoint.+disjoint :: Radix1Tree a -> Radix1Tree b -> Bool+disjoint = disjoint1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Unbiased intersection of two trees.+intersection :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+intersection = intersection1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Left-biased intersection of two trees.+intersectionL :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a+intersectionL = intersectionL1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Intersection of two trees with a combining function.+intersectionWith :: (a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+intersectionWith = intersectionWith1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Intersection of two trees with a combining function.+intersectionWithKey :: (Build1 -> a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+intersectionWithKey = intersectionWithKey1
+ src/Data/Radix1Tree/Word8/Lazy/Debug.hs view
@@ -0,0 +1,30 @@+{-|+    Safe functions for datatype introspection.+ -}++module Data.Radix1Tree.Word8.Lazy.Debug+  ( -- * Show+    showsTree++    -- * Validate+  , Validity (..)+  , Reason (..)+  , validate+  ) where++import           Data.RadixNTree.Word8.Lazy (Radix1Tree)+import           Data.RadixNTree.Word8.Lazy.Debug++++-- | \(\mathcal{O}(n)\).+--   Shows the internal structure of the tree.+showsTree :: (a -> ShowS) -> Radix1Tree a -> ShowS+showsTree = showsTree1++++-- | \(\mathcal{O}(n)\).+--   Checks whether the tree is well-formed.+validate :: Radix1Tree a -> Validity+validate = validate1
+ src/Data/Radix1Tree/Word8/Lazy/TH.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE TemplateHaskellQuotes #-}++{-|+    Template Haskell helper functions.+ -}++module Data.Radix1Tree.Word8.Lazy.TH+  ( sequenceCode+  ) where++import           Data.RadixNTree.Word8.Lazy.TH++import           Language.Haskell.TH.Syntax++++-- | \(\mathcal{O}(n)\).+--   Evaluate a tree of typed expressions.+sequenceCode :: Quote m => Radix1Tree (Code m a) -> Code m (Radix1Tree a)+sequenceCode = sequenceCode1
+ src/Data/Radix1Tree/Word8/Lazy/Unsafe.hs view
@@ -0,0 +1,218 @@+{-# LANGUAGE UnboxedTuples #-}++{-# OPTIONS_HADDOCK not-home #-}++{-|+    Data structure internals, helper operations and unsafe functions.+ -}++module Data.Radix1Tree.Word8.Lazy.Unsafe+  ( Radix1Tree (..)++    -- * Bit operations+  , Prefix+  , Key++    -- | === Compare+  , beyond+  , upper+  , lower++    -- | === Create+  , Mask+  , zeroBit+  , mask+  , branchingBit++    -- * Exceptions+  , MalformedTree (..)++    -- * Edges+    -- ** Lookup+  , Lookup1 (..)++    -- | === Min+  , unsafeLookupMin+  , unsafeLookupMinWithKey++    -- | === Max+  , unsafeLookupMax+  , unsafeLookupMaxWithKey++    -- ** Map+    -- | === Min+  , unsafeAdjustMin+  , unsafeAdjustMinWithKey++    -- | === Max+  , unsafeAdjustMax+  , unsafeAdjustMaxWithKey++    -- ** Delete+  , unsafeDeleteMin+  , unsafeDeleteMax++    -- ** Update+    -- | === Min+  , unsafeUpdateMin+  , unsafeUpdateMinWithKey++    -- | === Max+  , unsafeUpdateMax+  , unsafeUpdateMaxWithKey++    -- ** View+    -- | === Min+  , ViewL1 (..)+  , unsafeMinView++    -- | === Max+  , ViewR1 (..)+  , unsafeMaxView++    -- * Full-tree+    -- ** Merge+  , merge+  ) where++import           Data.RadixNTree.Word8.Key+import           Data.RadixNTree.Word8.Common+import           Data.RadixNTree.Word8.Lazy+import           Radix.Exception+import           Radix.Word.Foundation++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMin :: Radix1Tree a -> (# a #)+unsafeLookupMin = unsafeLookupMin1++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMinWithKey :: Radix1Tree a -> Lookup1 a+unsafeLookupMinWithKey = unsafeLookupMinWithKey1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Delete a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeDeleteMin :: Radix1Tree a -> Radix1Tree a+unsafeDeleteMin = unsafeDeleteMin1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMin :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMin = unsafeAdjustMin1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMinWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMinWithKey = unsafeAdjustMinWithKey1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeUpdateMin :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMin = unsafeUpdateMin1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeUpdateMinWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMinWithKey = unsafeUpdateMinWithKey1++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the leftmost value and return it alongside the tree without it.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeMinView :: Radix1Tree a -> ViewL1 a+unsafeMinView = unsafeMinView1++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMax :: Radix1Tree a -> (# a #)+unsafeLookupMax = unsafeLookupMax1++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMaxWithKey :: Radix1Tree a -> Lookup1 a+unsafeLookupMaxWithKey = unsafeLookupMaxWithKey1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Delete a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeDeleteMax :: Radix1Tree a -> Radix1Tree a+unsafeDeleteMax = unsafeDeleteMax1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMax :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMax = unsafeAdjustMax1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMaxWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMaxWithKey = unsafeAdjustMaxWithKey1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeUpdateMax :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMax = unsafeUpdateMax1++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeUpdateMaxWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMaxWithKey = unsafeUpdateMaxWithKey1++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the rightmost value and return it alongside the tree without it.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeMaxView :: Radix1Tree a -> ViewR1 a+unsafeMaxView = unsafeMaxView1++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   General merge of two trees.+--+--   Resulting 'Maybe's and 'Radix1Tree's in argument functions are evaluated to WHNF.+--+--   This functions inlines when all argument functions are provided.+{-# INLINE merge #-}+merge+  :: (Build1 -> a -> b -> Maybe c)           -- ^ Single value collision+  -> (Build1 -> a -> Maybe c)                -- ^ Single left value+  -> (Build -> Radix1Tree a -> Radix1Tree c) -- ^ Left subtree+  -> (Build1 -> b -> Maybe c)                -- ^ Single right value+  -> (Build -> Radix1Tree b -> Radix1Tree c) -- ^ Right subtree+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree c+merge = merge1
+ src/Data/Radix1Tree/Word8/Strict.hs view
@@ -0,0 +1,928 @@+{-|+    @'StrictRadix1Tree' a@ is a spine-strict radix tree that uses byte-aligned+    non-empty byte sequences as keys.++    == Laziness++    Evaluating the root of the tree (i.e. @(_ :: 'StrictRadix1Tree' a)@) to+    weak head normal form evaluates the entire spine of the tree to normal form.++    Functions do not perform any additional evaluations unless+    their documentation directly specifies so.++    == Performance++    Each function's time complexity is provided in the documentation.++    \(x\) is the length of the input key.++    \(k\) is the length of the longest key stored in the tree.++    \(n\) refers to the total number of entries in the tree.+    Parts of the tree are denoted using subscripts: \(n_L\) refers to the left side,+    \(n_R\) to the right side, and \(n_M\) to entries collected with the use of a 'Monoid'.++    == Inlining++    Functions that produce and consume 'Feed1's are treated specially within the library,+    as when combined they can be reduced in a manner similar to the+    [destroy/unfoldr elimination rule](https://wiki.haskell.org/Correctness_of_short_cut_fusion#destroy.2Funfoldr).++    The elimination in this library is achieved by inlining both types of functions+    heavily. To avoid unnecessary code duplication during compilation consider creating+    helper functions that apply these functions one to another, e.g.++    @updateBS f bs = 'update' f ('Data.Radix1Tree.Word8.Key.Unsafe.unsafeFeedByteString' bs)@++    N.B. To inline properly functions that consume 'Feed1's must mention all of the+         arguments except for the tree.++    == Implementation++    See the implementation section in "Data.RadixTree.Word8.Strict.Unsafe"+    for the explanation of the innerworkings.++    See the implementation section in "Data.Patricia.Word.Strict" for literary references.+ -}++module Data.Radix1Tree.Word8.Strict+  ( StrictRadix1Tree+  , Radix1Tree++  , RadixTree (..)++    -- * Key+  , module Data.Radix1Tree.Word8.Key++    -- * Construct+  , empty+  , singleton++    -- ** Convert+  , toLazy++    -- * Single-key+    -- ** Lookup+  , Data.Radix1Tree.Word8.Strict.lookup+  , Data.Radix1Tree.Word8.Strict.find+  , Data.Radix1Tree.Word8.Strict.member+  , subtree++    -- *** Chunked+    --+    -- | Chunked lookup allows providing the key piece by piece while retaining+    --   the ability to check for early failure.+    --+    --   Note that while 'subtree' can be used to achieve the same result,+    --   it is more expensive allocation-wise, as it must ensure that+    --   the resulting tree is well-formed after each chunk application.+  , Cursor+  , cursor+  , move+  , stop+  , Location (..)+  , locate++    -- ** Insert+  , insert+  , insertWith+  , insertWith'++    -- ** Map+  , adjust+  , adjust'++    -- ** Delete+  , delete+  , prune++    -- ** Update+  , update+  , alter+  , shape++    -- ** Take+  , SplitLookup1 (..)+  , splitLookup++    -- * Directional+  , Openness (..)++    -- ** Lookup+  , Lookup1 (..)+  , lookupL+  , lookupR++    -- ** Map+    -- | === Left+  , adjustL+  , adjustL'+  , adjustLWithKey+  , adjustLWithKey'++    -- | === Right+  , adjustR+  , adjustR'+  , adjustRWithKey+  , adjustRWithKey'++    -- ** Update+    -- | === Left+  , updateL+  , updateLWithKey++    -- | === Right+  , updateR+  , updateRWithKey++    -- ** Take+  , Split1 (..)++    -- | === Left+  , takeL+  , splitL++    -- | === Right+  , takeR++    -- * Edges++    -- ** Lookup+    -- | === Min+  , lookupMin+  , lookupMinWithKey++    -- | === Max+  , lookupMax+  , lookupMaxWithKey++    -- ** Map+    -- | === Min+  , adjustMin+  , adjustMin'+  , adjustMinWithKey+  , adjustMinWithKey'++    -- | === Max+  , adjustMax+  , adjustMax'+  , adjustMaxWithKey+  , adjustMaxWithKey'++    -- ** Delete+  , deleteMin+  , deleteMax++    -- ** Update+    -- | === Min+  , updateMin+  , updateMinWithKey++    -- | === Max+  , updateMax+  , updateMaxWithKey++    -- ** View+    -- | === Min+  , ViewL1 (..)+  , minView++    -- | === Max+  , ViewR1 (..)+  , maxView++    -- * Full tree+    -- ** Size+  , Data.Radix1Tree.Word8.Strict.null+  , size++    -- ** Extend+  , prefix++    -- ** Map+  , Data.Radix1Tree.Word8.Strict.map+  , map'+  , mapWithKey+  , mapWithKey'++    -- ** Fold+    -- | === Left-to-right+  , Data.Radix1Tree.Word8.Strict.foldl+  , Data.Radix1Tree.Word8.Strict.foldl'+  , foldlWithKey+  , foldlWithKey'++    -- | === Right-to-left+  , Data.Radix1Tree.Word8.Strict.foldr+  , Data.Radix1Tree.Word8.Strict.foldr'+  , foldrWithKey+  , foldrWithKey'++    -- | === Monoid+  , Data.Radix1Tree.Word8.Strict.foldMap+  , foldMapWithKey++    -- ** Traverse+  , Data.Radix1Tree.Word8.Strict.traverse+  , traverseWithKey++    -- ** Filter+    -- | === One side+  , Data.Radix1Tree.Word8.Strict.filter+  , filterWithKey++  , mapMaybe+  , mapMaybeWithKey++    -- | === Both sides+  , partition+  , partitionWithKey++  , mapEither+  , mapEitherWithKey++    -- ** Comparison+  , PartialOrdering (..)+  , Data.Radix1Tree.Word8.Strict.compare++    -- ** Union+  , union+  , unionL+  , unionWith'+  , unionWithKey'++    -- ** Difference+  , difference+  , differenceWith+  , differenceWithKey++    -- ** Intersection+  , disjoint+  , intersection+  , intersectionL+  , intersectionWith'+  , intersectionWithKey'++    -- ** Merge+    -- | See 'Data.Radix1Tree.Word8.Strict.Unsafe.merge'.+  ) where++import           Data.Radix1Tree.Word8.Key+import           Data.RadixNTree.Word8.Common+import           Data.RadixNTree.Word8.Conversion+import           Data.RadixNTree.Word8.Strict+import           Radix.Common++++-- | \(\mathcal{O}(1)\).+--   Empty tree.+empty :: Radix1Tree a+empty = empty1++{-# INLINE singleton #-}+-- | \(\mathcal{O}(x)\).+--   Tree with a single entry.+singleton :: Feed1 -> a -> Radix1Tree a+singleton = singleton1++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Create a lazy 'Lazy.Patricia' tree from a strict one.+--+--   The resulting tree does not share its data representation with the original.+toLazy :: StrictRadix1Tree a -> LazyRadix1Tree a+toLazy = toLazy1++++-- | \(\mathcal{O}(1)\).+--   Check if the tree is empty.+null :: Radix1Tree a -> Bool+null = null1++-- | \(\mathcal{O}(n)\).+--   Calculate the number of elements stored in the tree.+--   The returned number is guaranteed to be non-negative.+size :: Radix1Tree a -> Int+size = size1++++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+map :: (a -> b) -> Radix1Tree a -> Radix1Tree b+map = map1++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+map' :: (a -> b) -> Radix1Tree a -> Radix1Tree b+map' = map1'++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+mapWithKey :: (Build1 -> a -> b) -> Radix1Tree a -> Radix1Tree b+mapWithKey = mapWithKey1++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+mapWithKey' :: (Build1 -> a -> b) -> Radix1Tree a -> Radix1Tree b+mapWithKey' = mapWithKey1'++++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldl :: (b -> a -> b) -> b -> Radix1Tree a -> b+foldl = Data.RadixNTree.Word8.Strict.foldl1++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldlWithKey :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey = foldlWithKey1++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldl' :: (b -> a -> b) -> b -> Radix1Tree a -> b+foldl' = foldl1'++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldlWithKey' :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey' = foldlWithKey1'++++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldr :: (a -> b -> b) -> b -> Radix1Tree a -> b+foldr = Data.RadixNTree.Word8.Strict.foldr1++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldrWithKey :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey = foldrWithKey1++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldr' :: (a -> b -> b) -> b -> Radix1Tree a -> b+foldr' = foldr1'++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldrWithKey' :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey' = foldrWithKey1'++++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMap :: Monoid m => (a -> m) -> Radix1Tree a -> m+foldMap = foldMap1++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMapWithKey :: Monoid m => (Build1 -> a -> m) -> Radix1Tree a -> m+foldMapWithKey = foldMapWithKey1++++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverse :: Applicative f => (a -> f b) -> Radix1Tree a -> f (Radix1Tree b)+traverse = traverse1++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverseWithKey+  :: Applicative f => (Build1 -> a -> f b) -> Radix1Tree a -> f (Radix1Tree b)+traverseWithKey = traverseWithKey1++++-- | \(\mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filter :: (a -> Bool) -> Radix1Tree a -> Radix1Tree a+filter = filter1++-- | \(\mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filterWithKey :: (Build1 -> a -> Bool) -> Radix1Tree a -> Radix1Tree a+filterWithKey = filterWithKey1++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create one out of 'Just' values.+--+--   The 'Maybe' is evaluated to WHNF.+mapMaybe :: (a -> Maybe b) -> Radix1Tree a -> Radix1Tree b+mapMaybe = mapMaybe1++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create one out of 'Just' values.+--+--   The 'Maybe' is evaluated to WHNF.+mapMaybeWithKey :: (Build1 -> a -> Maybe b) -> Radix1Tree a -> Radix1Tree b+mapMaybeWithKey = mapMaybeWithKey1+++-- | \(\mathcal{O}(n)\).+--   Split1 the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partition :: (a -> Bool) -> Radix1Tree a -> Split1 a a+partition = partition1++-- | \(\mathcal{O}(n)\).+--   Split1 the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partitionWithKey :: (Build1 -> a -> Bool) -> Radix1Tree a -> Split1 a a+partitionWithKey = partitionWithKey1++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+--+--   The 'Either' is evaluated to WHNF.+mapEither :: (a -> Either b c) -> Radix1Tree a -> Split1 b c+mapEither = mapEither1++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+--+--   The 'Either' is evaluated to WHNF.+mapEitherWithKey :: (Build1 -> a -> Either b c) -> Radix1Tree a -> Split1 b c+mapEitherWithKey = mapEitherWithKey1++++{-# INLINE lookup #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the value at a key in the tree.+lookup :: Feed1 -> Radix1Tree a -> Maybe a+lookup = lookup1++{-# INLINE find #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the value at a key in the tree, falling back to the given default value+--   if it does not exist.+find :: a -> Feed1 -> Radix1Tree a -> a+find = find1++{-# INLINE member #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Check whether the value exists at a key in the tree.+member :: Feed1 -> Radix1Tree a -> Bool+member = member1++{-# INLINE subtree #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the part of the tree below the given prefix.+subtree :: Feed1 -> Radix1Tree a -> RadixTree a+subtree = subtree1++{-# INLINE prefix #-}+-- | \(\mathcal{O}(x)\).+--   Prefix the root of the tree with the given key.+prefix :: Feed1 -> RadixTree a -> Radix1Tree a+prefix = prefix1+++-- | \(\mathcal{O}(1)\).+--   Make a cursor that points to the root of the tree.+cursor :: Radix1Tree a -> Cursor a+cursor = cursor1++{-# INLINE move #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Move the cursor down by the extent of the given key.+move :: Feed1 -> Cursor a -> Cursor a+move = move1++++{-# INLINE insert #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, it is replaced.+insert :: Feed1 -> a -> Radix1Tree a -> Radix1Tree a+insert = insert1++{-# INLINE insertWith #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, the function is used instead.+insertWith :: (a -> a) -> Feed1 -> a -> Radix1Tree a -> Radix1Tree a+insertWith = insertWith1++{-# INLINE insertWith' #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, the function is used instead.+--+--   New value is evaluated to WHNF.+insertWith' :: (a -> a) -> Feed1 -> a -> Radix1Tree a -> Radix1Tree a+insertWith' = insertWith1'+++{-# INLINE adjust #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Apply a function to a value in the tree at the given key.+adjust :: (a -> a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjust = adjust1++{-# INLINE adjust' #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Apply a function to a value in the tree at the given key.+--+--   New value is evaluated to WHNF.+adjust' :: (a -> a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjust' = adjust1'+++{-# INLINE delete #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Delete a value in the tree at the given key.+delete :: Feed1 -> Radix1Tree a -> Radix1Tree a+delete = delete1++{-# INLINE prune #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Delete values in the tree below the given key.+prune :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+prune = prune1+++{-# INLINE update #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Update or delete a value in the tree at the given key.+--+--   The 'Maybe' is evaluated to WHNF.+update :: (a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+update = update1+++{-# INLINE alter #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Insert, update or delete a value in the tree at the given key.+--+--   The resulting 'Maybe' is evaluated to WHNF.+alter :: (Maybe a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+alter = alter1+++{-# INLINE shape #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Update the part of the tree at the given prefix.+--+--   The resulting 'Radix1Tree' is evaluated to WHNF.+shape :: (RadixTree a -> RadixTree a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+shape = shape1+++{-# INLINE splitLookup #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Split1 the tree into two, such that+--   values with keys smaller than the given one are on the left,+--   values with keys greater than the given one are on the right,+--   and the value at the given key is returned separately.+splitLookup :: Feed1 -> Radix1Tree a -> SplitLookup1 a a a+splitLookup = splitLookup1++++{-# INLINE lookupL #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up a value at a largest key smaller than (or equal to) the given key.+lookupL :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)+lookupL = lookupL1+++{-# INLINE lookupR #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up a value at a smallest key greater than (or equal to) the given key.+lookupR :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)+lookupR = lookupR1++++{-# INLINE adjustL #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+adjustL :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustL = adjustL1++{-# INLINE adjustL' #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+--+--   New value is evaluated to WHNF.+adjustL' :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustL' = adjustL1'++{-# INLINE adjustLWithKey #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+adjustLWithKey :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustLWithKey = adjustLWithKey1++{-# INLINE adjustLWithKey' #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+--+--   New value is evaluated to WHNF.+adjustLWithKey' :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustLWithKey' = adjustLWithKey1'++++{-# INLINE adjustR #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+adjustR :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustR = adjustR1++{-# INLINE adjustR' #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+--+--   New value is evaluated to WHNF.+adjustR' :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustR' = adjustR1'++{-# INLINE adjustRWithKey #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+adjustRWithKey :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustRWithKey = adjustRWithKey1++{-# INLINE adjustRWithKey' #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+--+--   New value is evaluated to WHNF.+adjustRWithKey' :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustRWithKey' = adjustRWithKey1'++++{-# INLINE updateL #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Update every value for which the key is smaller than (or equal to) the given one.+updateL :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateL = updateL1++{-# INLINE updateLWithKey #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Update every value for which the key is smaller than (or equal to) the given one.+--+--   The 'Maybe' is evaluated to WHNF.+updateLWithKey :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateLWithKey = updateLWithKey1++{-# INLINE updateR #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Update every value for which the key is greater than (or equal to) the given one.+updateR :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateR = updateR1++{-# INLINE updateRWithKey #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Update every value for which the key is greater than (or equal to) the given one.+--+--   The 'Maybe' is evaluated to WHNF.+updateRWithKey :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateRWithKey = updateRWithKey1++++{-# INLINE takeL #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Take values for which keys are smaller than (or equal to) the given one.+takeL :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+takeL = takeL1++{-# INLINE takeR #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Take values for which keys are greater than (or equal to) the given one.+takeR :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+takeR = takeR1++++{-# INLINE splitL #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Split1 the tree into two, such that+--   values with keys smaller than (or equal to) the given one are on the left,+--   and the rest are on the right.+splitL :: Openness -> Feed1 -> Radix1Tree a -> Split1 a a+splitL = splitL1++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+lookupMin :: Radix1Tree a -> Maybe a+lookupMin = lookupMin1++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+lookupMinWithKey :: Radix1Tree a -> Maybe (Lookup1 a)+lookupMinWithKey = lookupMinWithKey1++-- | \(\mathcal{O}(k)\).+--   Delete a value at the leftmost key in the tree.+deleteMin :: Radix1Tree a -> Radix1Tree a+deleteMin = deleteMin1++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+adjustMin :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMin = adjustMin1++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+adjustMinWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMinWithKey = adjustMinWithKey1++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMin' :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMin' = adjustMin1'++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMinWithKey' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMinWithKey' = adjustMinWithKey1'++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+updateMin :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMin = updateMin1++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+updateMinWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMinWithKey = updateMinWithKey1++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the leftmost value and return it alongside the tree without it.+minView :: Radix1Tree a -> Maybe (ViewL1 a)+minView = minView1++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+lookupMax :: Radix1Tree a -> Maybe a+lookupMax = lookupMax1++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+lookupMaxWithKey :: Radix1Tree a -> Maybe (Lookup1 a)+lookupMaxWithKey = lookupMaxWithKey1++-- | \(\mathcal{O}(k)\).+--   Delete a value at the rightmost key in the tree.+deleteMax :: Radix1Tree a -> Radix1Tree a+deleteMax = deleteMax1++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+adjustMax :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMax = adjustMax1++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+adjustMaxWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMaxWithKey = adjustMaxWithKey1++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMax' :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMax' = adjustMax1'++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMaxWithKey' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMaxWithKey' = adjustMaxWithKey1'++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+updateMax :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMax = updateMax1++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+updateMaxWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMaxWithKey = updateMaxWithKey1++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the rightmost value and return it alongside the tree without it.+maxView :: Radix1Tree a -> Maybe (ViewR1 a)+maxView = maxView1++++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Unbiased union of two trees.+union :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+union = union1++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Left-biased union of two trees.+unionL :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionL = unionL1++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Union of two trees with a combining function.+--+--   New values are evaluated to WHNF.+unionWith' :: (a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionWith' = unionWith1'++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Union of two trees with a combining function.+--+--   New values are evaluated to WHNF.+unionWithKey' :: (Build1 -> a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionWithKey' = unionWithKey1'++++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees.+difference :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a+difference = difference1++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees with a combining function.+--+--   The 'Maybe' is evaluated to WHNF.+differenceWith+  :: (a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a+differenceWith = differenceWith1++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees with a combining function.+--+--   The 'Maybe' is evaluated to WHNF.+differenceWithKey+  :: (Build1 -> a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a+differenceWithKey = differenceWithKey1++++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Compare two trees with respect to set inclusion,+--   using the given equality function for intersecting keys.+--   If any intersecting keys hold unequal values, the trees are 'Incomparable'.+compare :: (a -> b -> Bool) -> Radix1Tree a -> Radix1Tree b -> PartialOrdering+compare = compare1++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Determine whether two trees' key sets are disjoint.+disjoint :: Radix1Tree a -> Radix1Tree b -> Bool+disjoint = disjoint1++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Unbiased intersection of two trees.+intersection :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+intersection = intersection1++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Left-biased intersection of two trees.+intersectionL :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a+intersectionL = intersectionL1++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Intersection of two trees with a combining function.+--+--   New values are evaluated to WHNF.+intersectionWith' :: (a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+intersectionWith' = intersectionWith1'++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Intersection of two trees with a combining function.+--+--   New values are evaluated to WHNF.+intersectionWithKey' :: (Build1 -> a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+intersectionWithKey' = intersectionWithKey1'
+ src/Data/Radix1Tree/Word8/Strict/Debug.hs view
@@ -0,0 +1,30 @@+{-|+    Safe functions for datatype introspection.+ -}++module Data.Radix1Tree.Word8.Strict.Debug+  ( -- * Show+    showsTree++    -- * Validate+  , Validity (..)+  , Reason (..)+  , validate+  ) where++import           Data.RadixNTree.Word8.Strict (Radix1Tree)+import           Data.RadixNTree.Word8.Strict.Debug++++-- | \(\mathcal{O}(n)\).+--   Shows the internal structure of the tree.+showsTree :: (a -> ShowS) -> Radix1Tree a -> ShowS+showsTree = showsTree1++++-- | \(\mathcal{O}(n)\).+--   Checks whether the tree is well-formed.+validate :: Radix1Tree a -> Validity+validate = validate1
+ src/Data/Radix1Tree/Word8/Strict/TH.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE TemplateHaskellQuotes #-}++{-|+    Template Haskell helper functions.+ -}++module Data.Radix1Tree.Word8.Strict.TH+  ( sequenceCode+  ) where++import           Data.RadixNTree.Word8.Strict.TH++import           Language.Haskell.TH.Syntax++++-- | \(\mathcal{O}(n)\).+--   Evaluate a tree of typed expressions.+sequenceCode :: Quote m => Radix1Tree (Code m a) -> Code m (Radix1Tree a)+sequenceCode = sequenceCode1
+ src/Data/Radix1Tree/Word8/Strict/Unsafe.hs view
@@ -0,0 +1,250 @@+{-# LANGUAGE UnboxedTuples #-}++{-# OPTIONS_HADDOCK not-home #-}++{-|+    Data structure internals, helper operations and unsafe functions.+ -}++module Data.Radix1Tree.Word8.Strict.Unsafe+  ( Radix1Tree (..)++    -- * Bit operations+  , Prefix+  , Key++    -- | === Compare+  , beyond+  , upper+  , lower++    -- | === Create+  , Mask+  , zeroBit+  , mask+  , branchingBit++    -- * Exceptions+  , MalformedTree (..)++    -- * Edges+    -- ** Lookup+  , Lookup1 (..)++    -- | === Min+  , unsafeLookupMin+  , unsafeLookupMinWithKey++    -- | === Max+  , unsafeLookupMax+  , unsafeLookupMaxWithKey++    -- ** Map+    -- | === Min+  , unsafeAdjustMin+  , unsafeAdjustMin'+  , unsafeAdjustMinWithKey+  , unsafeAdjustMinWithKey'++    -- | === Max+  , unsafeAdjustMax+  , unsafeAdjustMax'+  , unsafeAdjustMaxWithKey+  , unsafeAdjustMaxWithKey'++    -- ** Delete+  , unsafeDeleteMin+  , unsafeDeleteMax++    -- ** Update+    -- | === Min+  , unsafeUpdateMin+  , unsafeUpdateMinWithKey++    -- | === Max+  , unsafeUpdateMax+  , unsafeUpdateMaxWithKey++    -- ** View+    -- | === Min+  , ViewL1 (..)+  , unsafeMinView++    -- | === Max+  , ViewR1 (..)+  , unsafeMaxView++    -- * Full-tree+    -- ** Merge+  , merge+  ) where++import           Data.RadixNTree.Word8.Key+import           Data.RadixNTree.Word8.Common+import           Data.RadixNTree.Word8.Strict+import           Radix.Exception+import           Radix.Word.Foundation++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMin :: Radix1Tree a -> (# a #)+unsafeLookupMin = unsafeLookupMin1++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMinWithKey :: Radix1Tree a -> Lookup1 a+unsafeLookupMinWithKey = unsafeLookupMinWithKey1++-- | \(\mathcal{O}(k)\).+--   Delete a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeDeleteMin :: Radix1Tree a -> Radix1Tree a+unsafeDeleteMin = unsafeDeleteMin1++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMin :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMin = unsafeAdjustMin1++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMinWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMinWithKey = unsafeAdjustMinWithKey1++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+--+--   New value is evaluated to WHNF.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMin' :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMin' = unsafeAdjustMin1'++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+--+--   New value is evaluated to WHNF.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMinWithKey' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMinWithKey' = unsafeAdjustMinWithKey1'++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+unsafeUpdateMin :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMin = unsafeUpdateMin1++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+unsafeUpdateMinWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMinWithKey = unsafeUpdateMinWithKey1++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the leftmost value and return it alongside the tree without it.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeMinView :: Radix1Tree a -> ViewL1 a+unsafeMinView = unsafeMinView1++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMax :: Radix1Tree a -> (# a #)+unsafeLookupMax = unsafeLookupMax1++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeLookupMaxWithKey :: Radix1Tree a -> Lookup1 a+unsafeLookupMaxWithKey = unsafeLookupMaxWithKey1++-- | \(\mathcal{O}(k)\).+--   Delete a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeDeleteMax :: Radix1Tree a -> Radix1Tree a+unsafeDeleteMax = unsafeDeleteMax1++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMax :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMax = unsafeAdjustMax1++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMaxWithKey :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMaxWithKey = unsafeAdjustMaxWithKey1++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+--+--   New value is evaluated to WHNF.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMax' :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMax' = unsafeAdjustMax1'++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+--+--   New value is evaluated to WHNF.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeAdjustMaxWithKey' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMaxWithKey' = unsafeAdjustMaxWithKey1'++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+unsafeUpdateMax :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMax = unsafeUpdateMax1++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+unsafeUpdateMaxWithKey :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMaxWithKey = unsafeUpdateMaxWithKey1++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the rightmost value and return it alongside the tree without it.+--+--   Throws 'MalformedTree' if the tree is empty.+unsafeMaxView :: Radix1Tree a -> ViewR1 a+unsafeMaxView = unsafeMaxView1++++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   General merge of two trees.+--+--   Resulting 'Maybe's and 'Radix1Tree's in argument functions are evaluated to WHNF.+--+--   This functions inlines when all argument functions are provided.+{-# INLINE merge #-}+merge+  :: (Build1 -> a -> b -> Maybe c)           -- ^ Single value collision+  -> (Build1 -> a -> Maybe c)                -- ^ Single left value+  -> (Build -> Radix1Tree a -> Radix1Tree c) -- ^ Left subtree+  -> (Build1 -> b -> Maybe c)                -- ^ Single right value+  -> (Build -> Radix1Tree b -> Radix1Tree c) -- ^ Right subtree+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree c+merge = merge1
+ src/Data/RadixNTree/Word8/Common.hs view
@@ -0,0 +1,25 @@+module Data.RadixNTree.Word8.Common+  ( Lookup (..)+  , Lookup1 (..)++  , Openness (..)+  ) where++import           Data.RadixNTree.Word8.Key++++-- | Key together with the value.+data Lookup a = Lookup !Build a+                deriving Show++-- | Key together with the value.+data Lookup1 a = Lookup1 !Build1 a+                 deriving Show++++-- | Whether the endpoint itself is included in the interval.+data Openness = Open   -- ^ Excluding the point.+              | Closed -- ^ Including the point.+                deriving Show
+ src/Data/RadixNTree/Word8/Conversion.hs view
@@ -0,0 +1,38 @@+module Data.RadixNTree.Word8.Conversion+  ( Lazy.LazyRadixTree+  , Lazy.LazyRadix1Tree+  , toLazy0+  , toLazy1++  , Strict.StrictRadixTree+  , Strict.StrictRadix1Tree+  , toStrict0+  , toStrict1+  ) where++import qualified Data.RadixNTree.Word8.Lazy as Lazy+import qualified Data.RadixNTree.Word8.Strict as Strict++++toLazy0 :: Strict.StrictRadixTree a -> Lazy.LazyRadixTree a+toLazy0 (Strict.RadixTree mx t) = Lazy.RadixTree mx (toLazy1 t)++toLazy1 :: Strict.StrictRadix1Tree a -> Lazy.LazyRadix1Tree a+toLazy1 t =+  case t of+    Strict.Bin p l r     -> Lazy.Bin p (toLazy1 l) (toLazy1 r)+    Strict.Tip arr mx dx -> Lazy.Tip arr mx (toLazy1 dx)+    Strict.Nil           -> Lazy.Nil++++toStrict0 :: Lazy.LazyRadixTree a -> Strict.StrictRadixTree a+toStrict0 (Lazy.RadixTree mx t) = Strict.RadixTree mx (toStrict1 t)++toStrict1 :: Lazy.LazyRadix1Tree a -> Strict.StrictRadix1Tree a+toStrict1 t =+  case t of+    Lazy.Bin p l r     -> Strict.Bin p (toStrict1 l) (toStrict1 r)+    Lazy.Tip arr mx dx -> Strict.Tip arr mx (toStrict1 dx)+    Lazy.Nil           -> Strict.Nil
+ src/Data/RadixNTree/Word8/Debug.hs view
@@ -0,0 +1,29 @@+module Data.RadixNTree.Word8.Debug+  ( Validity (..)+  , Reason (..)+  ) where++import           Data.RadixNTree.Word8.Key+import           Radix.Word8.Foundation++++-- | Whether the tree is well-formed.+data Validity = Valid+              | Invalid Build Reason+                deriving Show++-- | Reason for why the tree is considered malformed.+data Reason = -- | Prefix is @0@.+              ZeroPrefix+              -- | Prefix below diverges from the prefix above.+            | PrefixBelow Prefix Prefix+              -- | Key diverges the prefix above.+            | KeyBelow Prefix Key+              -- | One of the branches is empty.+            | MalformedBin Prefix+              -- | Empty 'Data.Array.Byte.ByteArray'.+            | EmptyByteArray+              -- | @Tip@ stores no value and is not followed by a @Bin@.+            | UncompressedTip+              deriving Show
+ src/Data/RadixNTree/Word8/Key.hs view
@@ -0,0 +1,379 @@+{-# LANGUAGE BangPatterns+           , RankNTypes #-}++module Data.RadixNTree.Word8.Key+  ( Tsil (..)+  , YtpmeNon (..)+  , Build (..)++  , buildBytes0++  , buildByteString0+  , buildShortByteString0++  , unsafeBuildText0++  , Build1 (..)++  , buildBytes1++  , buildByteString1+  , buildShortByteString1++  , unsafeBuildText1++  , Feed (..)+  , feedBytes0++  , feedByteString0+  , feedShortByteString0+  , feedLazyByteString0++  , feedText0+  , feedLazyText0++  , Feed1 (..)+  , feedBytes1++  , unsafeFeedByteString1+  , unsafeFeedShortByteString1+  , unsafeFeedLazyByteString1++  , unsafeFeedText1+  , unsafeFeedLazyText1+  ) where++import           Data.ByteArray.NonEmpty++import           Control.Monad.ST+import qualified Data.ByteString as BS+import qualified Data.ByteString.Internal as Strict (ByteString (..), unsafeCreate)+import qualified Data.ByteString.Lazy as Lazy (ByteString)+import qualified Data.ByteString.Lazy.Internal as LazyBS (ByteString (..))+import           Data.ByteString.Short.Internal (ShortByteString (..))+import           Data.ByteString.Unsafe+import           Data.List.NonEmpty (NonEmpty (..))+import           Data.Primitive.ByteArray+import qualified Data.Text.Array as Array+import qualified Data.Text.Internal as Strict (Text (..))+import qualified Data.Text.Internal.Lazy as LazyText (Text (..))+import qualified Data.Text.Lazy as Lazy (Text)+import           Data.Word+import           Foreign.Ptr++++-- | Snoc-list.+data Tsil a = Lin+            | Snoc (Tsil a) a++-- | Snoc-list with a guaranteed element at the back.+data YtpmeNon a = Tsil a :/ a++-- | Key as stored in the radix tree.+newtype Build = Build+                  -- | List of memory chunks that constitute the key.+                  --+                  --   The first chunk is at the bottom of the list.+                  (Tsil ByteArray)++instance Show Build where+  showsPrec d = showsPrec d . buildBytes0++-- | Non-empty key as stored in the radix tree.+newtype Build1 = Build1+                   -- | List of memory chunks that constitute the key.+                   --+                   --   The first chunk is at the bottom of the list.+                   (YtpmeNon ByteArray)++instance Show Build1 where+  showsPrec d xs = let ~(y :| ys) = buildBytes1 xs+                   in showsPrec d (y:ys)++buildBytes0 :: Build -> [Word8]+buildBytes0 (Build xs) = go [] xs+  where+    go acc as =+      case as of+        Snoc bs a -> go (Data.ByteArray.NonEmpty.toList a <> acc) bs+        Lin       -> acc++buildBytes1 :: Build1 -> NonEmpty Word8+buildBytes1 (Build1 (xs :/ x)) = go (toNonEmpty x) xs+  where+    go acc as =+      case as of+        Snoc bs a -> go (toNonEmpty a <> acc) bs+        Lin       -> acc++++sizeofBuild0 :: Build -> Int+sizeofBuild0 (Build xs) = go xs+  where+    go as =+      case as of+        Snoc bs arr -> sizeofByteArray arr + go bs+        Lin         -> 0++sizeofBuild1 :: Build1 -> Int+sizeofBuild1 (Build1 (xs :/ arr)) = sizeofByteArray arr + sizeofBuild0 (Build xs)++writePtr :: Ptr Word8 -> Int -> Build -> IO ()+writePtr ptr off0 (Build xs) = go off0 xs+  where+    go off as =+      case as of+        Snoc bs arr -> do+          let off' = off - sizeofByteArray arr+          copyByteArrayToAddr (plusPtr ptr off') arr 0 (sizeofByteArray arr)+          go off' bs++        Lin         -> pure ()++writePtr1 :: Ptr Word8 -> Int -> Build1 -> IO ()+writePtr1 ptr off (Build1 (xs :/ arr)) = do+  let off' = off - sizeofByteArray arr+  copyByteArrayToAddr (plusPtr ptr off') arr 0 (sizeofByteArray arr)+  writePtr ptr off' (Build xs)++++buildByteString0 :: Build -> Strict.ByteString+buildByteString0 xs =+  let len = sizeofBuild0 xs+  in Strict.unsafeCreate len (\ptr -> writePtr ptr len xs)++buildByteString1 :: Build1 -> Strict.ByteString+buildByteString1 xs =+  let len = sizeofBuild1 xs+  in Strict.unsafeCreate len (\ptr -> writePtr1 ptr len xs)++++writeArr :: MutableByteArray s -> Int -> Build -> ST s ()+writeArr marr off0 (Build xs) = go off0 xs+  where+    go off as =+      case as of+        Snoc bs arr -> do+          let off' = off - sizeofByteArray arr+          copyByteArray marr off' arr 0 (sizeofByteArray arr)+          go off' bs++        Lin         -> pure ()++writeArr1 :: MutableByteArray s -> Int -> Build1 -> ST s ()+writeArr1 marr off (Build1 (xs :/ arr)) = do+  let off' = off - sizeofByteArray arr+  copyByteArray marr off' arr 0 (sizeofByteArray arr)+  writeArr marr off' (Build xs)++++{-# INLINE buildShortByteString0 #-}+buildShortByteString0 :: Build -> ShortByteString+buildShortByteString0 xs =+  runST $ do+    let len = sizeofBuild0 xs+    marr <- newByteArray len+    writeArr marr len xs+    ByteArray arr <- unsafeFreezeByteArray marr+    pure $ SBS arr++{-# INLINE buildShortByteString1 #-}+buildShortByteString1 :: Build1 -> ShortByteString+buildShortByteString1 xs =+  runST $ do+    let len = sizeofBuild1 xs+    marr <- newByteArray len+    writeArr1 marr len xs+    ByteArray arr <- unsafeFreezeByteArray marr+    pure $ SBS arr++{-# INLINE unsafeBuildText0 #-}+unsafeBuildText0 :: Build -> Strict.Text+unsafeBuildText0 xs =+  runST $ do+    let len = sizeofBuild0 xs+    marr <- newByteArray len+    writeArr marr len xs+    ByteArray arr <- unsafeFreezeByteArray marr+    pure $ Strict.Text (Array.ByteArray arr) 0 len++{-# INLINE unsafeBuildText1 #-}+unsafeBuildText1 :: Build1 -> Strict.Text+unsafeBuildText1 xs =+  runST $ do+    let len = sizeofBuild1 xs+    marr <- newByteArray len+    writeArr1 marr len xs+    ByteArray arr <- unsafeFreezeByteArray marr+    pure $ Strict.Text (Array.ByteArray arr) 0 len++++-- | Key as a sequence of individual bytes.+newtype Feed = Feed+                 -- | @destroy@ part of the @destroy/unfoldr@ rule.+                 (forall a. (forall x. (x -> Step Word8 x) -> x -> a) -> a)++{-# INLINE vomit #-}+vomit :: (x -> Step a x) -> x -> [a]+vomit step = go+  where+    go s =+      case step s of+        More w ws -> w : go ws+        Done      -> []++instance Show Feed where+  showsPrec d (Feed f) = showsPrec d $ f vomit++noFeed :: Feed+noFeed = Feed $ \f -> f (\_ -> Done) ()++{-# INLINE feedBytes0 #-}+feedBytes0 :: [Word8] -> Feed+feedBytes0 ws0 = Feed $ \f -> f go ws0+  where+    go (w:ws) = More w ws+    go []     = Done++++-- | Key as a non-empty sequence of individual bytes.+data Feed1 = Feed1+               -- | First byte of the key.+               {-# UNPACK #-} !Word8++               -- | @destroy@ part of the @destroy/unfoldr@ rule.+               (forall a. (forall x. (x -> Step Word8 x) -> x -> a) -> a)++instance Show Feed1 where+  showsPrec d (Feed1 w0 f) = showsPrec d $ w0 :| f vomit++{-# INLINE feedBytes1 #-}+feedBytes1 :: NonEmpty Word8 -> Feed1+feedBytes1 (w0 :| ws) =+  let Feed f = feedBytes0 ws+  in Feed1 w0 f+++++stepByteString :: Strict.ByteString -> Int -> Step Word8 Int+stepByteString bs = go+  where+    go n =+      if n >= BS.length bs+        then Done+        else let !n' = n + 1+             in More (unsafeIndex bs n) n'++{-# INLINE feedByteString0 #-}+feedByteString0 :: Strict.ByteString -> Feed+feedByteString0 bs = Feed $ \f -> f (stepByteString bs) 0++{-# INLINE unsafeFeedByteString1 #-}+unsafeFeedByteString1 :: Strict.ByteString -> Feed1+unsafeFeedByteString1 bs = Feed1 (unsafeIndex bs 0) (\f -> f (stepByteString bs) 1)++++stepByteArray :: ByteArray -> Int -> Int -> Step Word8 Int+stepByteArray arr len = go+  where+    go n =+      if n >= len+        then Done+        else let !n' = n + 1+             in More (indexByteArray arr n) n'++{-# INLINE feedShortByteString0 #-}+feedShortByteString0 :: ShortByteString -> Feed+feedShortByteString0 (SBS arr) =+  Feed $ \f ->+    f (stepByteArray (ByteArray arr) $ sizeofByteArray (ByteArray arr)) 0++{-# INLINE unsafeFeedShortByteString1 #-}+unsafeFeedShortByteString1 :: ShortByteString -> Feed1+unsafeFeedShortByteString1 (SBS arr) =+  Feed1 (indexByteArray (ByteArray arr) 0) $ \f ->+    f (stepByteArray (ByteArray arr) $ sizeofByteArray (ByteArray arr)) 1++++{-# INLINE feedText0 #-}+feedText0 :: Strict.Text -> Feed+feedText0 (Strict.Text (Array.ByteArray arr) n len) =+  Feed $ \f ->+    f (stepByteArray (ByteArray arr) len) n++{-# INLINE unsafeFeedText1 #-}+unsafeFeedText1 :: Strict.Text -> Feed1+unsafeFeedText1 (Strict.Text (Array.ByteArray arr) n len) =+  Feed1 (indexByteArray (ByteArray arr) n) $ \f ->+    let !n' = n + 1+    in f (stepByteArray (ByteArray arr) len) n'++++data CarryBS = CarryBS Int Strict.ByteString Lazy.ByteString++{-# INLINE stepLazyByteString #-}+stepLazyByteString :: CarryBS -> Step Word8 CarryBS+stepLazyByteString (CarryBS n bs lbs) =+  if n >= BS.length bs+    then case lbs of+           LazyBS.Chunk bs' lbs' -> stepLazyByteString (CarryBS 0 bs' lbs')+           LazyBS.Empty          -> Done++    else let !n' = n + 1+         in More (unsafeIndex bs n) (CarryBS n' bs lbs)++{-# INLINE feedLazyByteString0 #-}+feedLazyByteString0 :: Lazy.ByteString -> Feed+feedLazyByteString0 b =+  case b of+    LazyBS.Empty        -> noFeed+    LazyBS.Chunk bs lbs -> Feed $ \f -> f stepLazyByteString (CarryBS 0 bs lbs)++{-# INLINE unsafeFeedLazyByteString1 #-}+unsafeFeedLazyByteString1 :: Strict.ByteString -> Lazy.ByteString -> Feed1+unsafeFeedLazyByteString1 bs lbs =+  Feed1 (unsafeIndex bs 0) $ \f ->+    f stepLazyByteString (CarryBS 1 bs lbs)++++data CarryTxt = CarryTxt Int Int ByteArray Lazy.Text++{-# INLINE stepLazyText #-}+stepLazyText :: CarryTxt -> Step Word8 CarryTxt+stepLazyText (CarryTxt n len arr t) =+  if n >= len+    then case t of+           LazyText.Chunk (Strict.Text (Array.ByteArray arr') n' len') t' ->+             stepLazyText (CarryTxt n' len' (ByteArray arr') t')++           LazyText.Empty -> Done++    else let !n' = n + 1+         in More (indexByteArray arr n) (CarryTxt n' len arr t)++{-# INLINE feedLazyText0 #-}+feedLazyText0 :: Lazy.Text -> Feed+feedLazyText0 t =+  case t of+    LazyText.Empty                                                -> noFeed+    LazyText.Chunk (Strict.Text (Array.ByteArray arr) n len) ltxt ->+      Feed $ \f -> f stepLazyText (CarryTxt n len (ByteArray arr) ltxt)++{-# INLINE unsafeFeedLazyText1 #-}+unsafeFeedLazyText1 :: Strict.Text -> Lazy.Text -> Feed1+unsafeFeedLazyText1 (Strict.Text (Array.ByteArray arr) n len) ltxt =+  Feed1 (indexByteArray (ByteArray arr) n) $ \f ->+    let !n' = n + 1+    in f stepLazyText (CarryTxt n' len (ByteArray arr) ltxt)
+ src/Data/RadixNTree/Word8/Lazy.hs view
@@ -0,0 +1,5076 @@+{-# LANGUAGE BangPatterns+           , GADTs+           , RankNTypes+           , ScopedTypeVariables+           , UnboxedTuples #-}++module Data.RadixNTree.Word8.Lazy+  ( LazyRadixTree+  , RadixTree (..)++  , LazyRadix1Tree+  , Radix1Tree (..)++  , empty0+  , empty1++  , singleton0+  , singleton1++  , map0+  , mapWithKey0++  , map1+  , mapWithKey1++  , foldl0+  , foldl0'+  , foldlWithKey0+  , foldlWithKey0'++  , Data.RadixNTree.Word8.Lazy.foldl1+  , foldl1'+  , foldlWithKey1+  , foldlWithKey1'++  , foldr0+  , foldr0'+  , foldrWithKey0+  , foldrWithKey0'++  , Data.RadixNTree.Word8.Lazy.foldr1+  , foldr1'+  , foldrWithKey1+  , foldrWithKey1'++  , foldMap0+  , foldMapWithKey0++  , foldMap1+  , foldMapWithKey1++  , traverse0+  , traverseWithKey0++  , traverse1+  , traverseWithKey1++  , null0+  , null1++  , size0+  , size1++  , lookup0+  , find0+  , member0+  , subtree0+  , prefix0++  , lookup1+  , find1+  , member1+  , subtree1+  , prefix1++  , Point (..)+  , Cursor (..)+  , stop++  , Location (..)+  , locate++  , cursor0+  , move0++  , cursor1+  , move1++  , lookupL0+  , lookupL1++  , lookupR0+  , lookupR1++  , adjustL0+  , adjustLWithKey0++  , adjustL1+  , adjustLWithKey1++  , adjustR0+  , adjustRWithKey0++  , adjustR1+  , adjustRWithKey1++  , updateL0+  , updateLWithKey0++  , updateL1+  , updateLWithKey1++  , updateR0+  , updateRWithKey0++  , updateR1+  , updateRWithKey1++  , takeL0+  , takeL1++  , takeR0+  , takeR1++  , union0+  , union1++  , unionL0+  , unionL1++  , unionWith0+  , unionWith1++  , unionWithKey0+  , unionWithKey1++  , difference0+  , difference1++  , differenceWith0+  , differenceWith1++  , differenceWithKey0+  , differenceWithKey1++  , compare0+  , Data.RadixNTree.Word8.Lazy.compare1++  , disjoint0+  , disjoint1++  , intersection0+  , intersection1++  , intersectionL0+  , intersectionL1++  , intersectionWith0+  , intersectionWith1++  , intersectionWithKey0+  , intersectionWithKey1++  , merge0+  , merge1++  , insert0+  , insert1++  , insertWith0+  , insertWith1++  , adjust0+  , adjust1++  , delete0+  , delete1++  , prune0+  , prune1++  , update0+  , update1++  , alter0+  , alter1++  , shape0+  , shape1++  , splitL0+  , splitL1++  , splitLookup0+  , splitLookup1++  , filter0+  , filterWithKey0++  , filter1+  , filterWithKey1++  , mapMaybe0+  , mapMaybeWithKey0++  , mapMaybe1+  , mapMaybeWithKey1++  , partition0+  , partitionWithKey0++  , partition1+  , partitionWithKey1++  , mapEither0+  , mapEitherWithKey0++  , mapEither1+  , mapEitherWithKey1++  , lookupMin0+  , lookupMin1+  , unsafeLookupMin1++  , lookupMinWithKey0+  , lookupMinWithKey1+  , unsafeLookupMinWithKey1++  , lookupMax0+  , lookupMax1+  , unsafeLookupMax1++  , lookupMaxWithKey0+  , lookupMaxWithKey1+  , unsafeLookupMaxWithKey1++  , deleteMin0+  , deleteMin1+  , unsafeDeleteMin1++  , deleteMax0+  , deleteMax1+  , unsafeDeleteMax1++  , adjustMin0+  , adjustMin1+  , unsafeAdjustMin1++  , adjustMinWithKey0+  , adjustMinWithKey1+  , unsafeAdjustMinWithKey1++  , adjustMax0+  , adjustMax1+  , unsafeAdjustMax1++  , adjustMaxWithKey0+  , adjustMaxWithKey1+  , unsafeAdjustMaxWithKey1++  , updateMin0+  , updateMin1+  , unsafeUpdateMin1++  , updateMinWithKey0+  , updateMinWithKey1+  , unsafeUpdateMinWithKey1++  , updateMax0+  , updateMax1+  , unsafeUpdateMax1++  , updateMaxWithKey0+  , updateMaxWithKey1+  , unsafeUpdateMaxWithKey1++  , ViewL (..)+  , ViewL1 (..)+  , minView0+  , minView1+  , unsafeMinView1++  , ViewR (..)+  , ViewR1 (..)+  , maxView0+  , maxView1+  , unsafeMaxView1+  ) where++import           Data.ByteArray.NonEmpty+import           Data.RadixNTree.Word8.Common+import           Data.RadixNTree.Word8.Key+import           Radix.Common+import           Radix.Exception+import           Radix.Word8.Common+import           Radix.Word8.Foundation++import           Control.Applicative+import           Control.Exception (throw)+import           Control.DeepSeq+import           Data.Bits+import           Data.Foldable+import           Data.Functor.Classes+import           Data.Primitive.ByteArray+import           Data.Word+import           Text.Show++++-- | Convenience type synonym.+type LazyRadixTree = RadixTree++-- | Spine-strict radix tree with byte sequences as keys.+data RadixTree a = RadixTree+                     {-# UNPACK #-} !(Maybe a) -- ^ Value at the empty byte sequence key.+                     (Radix1Tree a)++instance Show a => Show (RadixTree a) where+  showsPrec = liftShowsPrec showsPrec showList++instance Show1 RadixTree where+  liftShowsPrec showsPrec_ showList_ d t =+    showParen (d > 10) $+      showListWith (liftShowsPrec showsPrec_ showList_ 0) $+        foldrWithKey0 (\k a -> (:) (k, a)) [] t++instance Eq a => Eq (RadixTree a) where+  (==) = liftEq (==)++instance Eq1 RadixTree where+  liftEq eq (RadixTree mx l) (RadixTree my r) = liftEq eq mx my && liftEq eq l r++-- | Uses 'Data.RadixTree.Word8.Lazy.map'.+instance Functor RadixTree where+  fmap = map0++instance Foldable RadixTree where+  foldl = foldl0+  foldr = foldr0+  foldMap = foldMap0++  foldl' = foldl0'+  foldr' = foldr0'++  null = null0++  length = size0++instance Traversable RadixTree where+  traverse = traverse0+++instance NFData a => NFData (RadixTree a) where+  rnf = liftRnf rnf++instance NFData1 RadixTree where+  liftRnf nf (RadixTree mx t) = liftRnf nf mx `seq` liftRnf nf t++++-- | Convenience type synonym.+type LazyRadix1Tree = Radix1Tree++-- | Spine-strict radix tree with non-empty byte sequences as keys.+data Radix1Tree a = Bin+                      {-# UNPACK #-} !Prefix+                      (Radix1Tree a)         -- ^ Masked bit is @0@. Invariant: not 'Nil'.+                      (Radix1Tree a)         -- ^ Masked bit is @1@. Invariant: not 'Nil'.++                  | Tip+                      {-# UNPACK #-} !ByteArray -- ^ Invariant: non-empty.+                      {-# UNPACK #-} !(Maybe a) -- ^ Invariant: can only be 'Nothing' when+                                                --   the tree below is 'Bin'.+                      (Radix1Tree a)++                  | Nil++instance Show a => Show (Radix1Tree a) where+  showsPrec = liftShowsPrec showsPrec showList++instance Show1 Radix1Tree where+  liftShowsPrec showsPrec_ showList_ d t =+    showParen (d > 10) $+      showListWith (liftShowsPrec showsPrec_ showList_ 0) $+        foldrWithKey1 (\k a -> (:) (k, a)) [] t++instance Eq a => Eq (Radix1Tree a) where+  (==) = liftEq (==)++instance Eq1 Radix1Tree where+  liftEq eq = go+    where+      go l r =+        case l of+          Bin p xl xr ->+            case r of+              Bin q yl yr -> p == q && go xl yl && go xr yr+              _           -> False++          Tip arr mx dx ->+            case r of+              Tip brr my dy -> arr == brr && liftEq eq mx my && go dx dy+              _             -> False++          Nil ->+            case r of+              Nil -> True+              _   -> False++-- | Uses 'Data.Radix1Tree.Word8.Lazy.map'.+instance Functor Radix1Tree where+  fmap = map1++instance Foldable Radix1Tree where+  foldl = Data.RadixNTree.Word8.Lazy.foldl1+  foldr = Data.RadixNTree.Word8.Lazy.foldr1+  foldMap = foldMap1++  foldl' = foldl1'+  foldr' = foldr1'++  null = null1++  length = size1++instance Traversable Radix1Tree where+  traverse = traverse1+++instance NFData a => NFData (Radix1Tree a) where+  rnf = liftRnf rnf++instance NFData1 Radix1Tree where+  liftRnf nf = go+    where+      go t =+        case t of+          Bin _ l r   -> go l `seq` go r+          Tip _ mx dx -> liftRnf nf mx `seq` go dx+          Nil         -> ()+++++{-# INLINE join #-}+-- | Knowing that the prefices of two trees disagree, construct a 'Bin'.+join :: Prefix -> Radix1Tree a -> Prefix -> Radix1Tree a -> Radix1Tree a+join p0 t0 p1 t1 =+  let m = branchingBit p0 p1++      p = mask p0 m .|. m++  in if zeroBit p0 m+       then Bin p t0 t1+       else Bin p t1 t0++{-# INLINE safeJoin #-}+safeJoin :: Prefix -> Radix1Tree a -> Prefix -> Radix1Tree a -> Radix1Tree a+safeJoin _ Nil _  t1    = t1+safeJoin _ t0    _  Nil = t0+safeJoin p0 t0   p1 t1  = join p0 t0 p1 t1++{-# INLINE retip #-}+-- | Based on the altered entry and/or downward state, fuse or remove the 'Tip' as needed.+retip :: ByteArray -> Maybe a -> Radix1Tree a -> Radix1Tree a+retip arr mx dx =+  case mx of+    Just _  -> Tip arr mx dx+    Nothing ->+     case dx of+       Bin _ _ _     -> Tip arr mx dx+       Tip brr my dy -> Tip (appendByteArray arr brr) my dy+       Nil           -> Nil++{-# INLINE dropTrim #-}+dropTrim :: Int -> ByteArray -> Maybe a -> Radix1Tree a -> Radix1Tree a+dropTrim n arr mx dx =+  case mx of+    Just _  -> Tip (dropByteArray n arr) mx dx+    Nothing ->+     case dx of+       Bin _ _ _     -> Tip (dropByteArray n arr) mx dx+       Tip brr my dy -> Tip (dropAppendByteArray n arr brr) my dy+       Nil           -> Nil+++{-# INLINE rebin #-}+rebin :: Prefix -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+rebin p l r =+  case l of+    Nil -> r+    _     -> case r of+               Nil -> l+               _     -> Bin p l r++{-# INLINE rebinL #-}+rebinL :: Prefix -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+rebinL p l r =+  case l of+    Nil -> r+    _   -> Bin p l r++{-# INLINE rebinR #-}+rebinR :: Prefix -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+rebinR p l r =+  case r of+    Nil -> l+    _   -> Bin p l r++++empty0 :: RadixTree a+empty0 = RadixTree Nothing Nil++empty1 :: Radix1Tree a+empty1 = Nil++++{-# INLINE singleton0 #-}+singleton0 :: Feed -> a -> RadixTree a+singleton0 (Feed feed) = \a ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree Nothing $ singleton1 (Feed1 w (\g -> g step z)) a+      Done     -> RadixTree (Just a) Nil++{-# INLINE singleton1 #-}+singleton1 :: Feed1 -> a -> Radix1Tree a+singleton1 (Feed1 w feed) = \a -> feed $ \step s -> singleton_ step w s a++{-# INLINE singleton_ #-}+-- | \(\mathcal{O}(1)\). Single element radix tree.+singleton_ :: (b -> Step Word8 b) -> Word8 -> b -> a -> Radix1Tree a+singleton_ step w s = \a -> Tip (fromStep step w s) (Just a) Nil++++null0 :: RadixTree a -> Bool+null0 (RadixTree Nothing t) = null1 t+null0 _                     = False++null1 :: Radix1Tree a -> Bool+null1 Nil = True+null1 _   = False++++size0 :: RadixTree a -> Int+size0 (RadixTree mx t) =+  let !n = size1 t+  in case mx of+       Just _  -> n + 1+       Nothing -> n++size1 :: Radix1Tree a -> Int+size1 = go 0+  where+    go z t =+      case t of+        Bin _ l r   -> let !n = go z l+                       in go n r++        Tip _ mx dx -> case mx of+                         Nothing -> go z dx+                         Just _  -> let !n = go z dx+                                    in n + 1+        Nil         -> z++++{-# INLINE fmap' #-}+fmap' :: (a -> b) -> Maybe a -> Maybe b+fmap' f (Just x) = Just $! f x+fmap' _ Nothing  = Nothing++++map0 :: (a -> b) -> RadixTree a -> RadixTree b+map0 f (RadixTree mx t) = RadixTree (fmap f mx) $ map1 f t++map1 :: (a -> b) -> Radix1Tree a -> Radix1Tree b+map1 f = go+  where+    go t =+      case t of+        Bin p l r     -> Bin p (go l) (go r)+        Tip arr mx dx -> Tip arr (fmap f mx) (go dx)+        Nil           -> Nil++++mapWithKey0 :: (Build -> a -> b) -> RadixTree a -> RadixTree b+mapWithKey0 f (RadixTree mx t) =+  RadixTree (f (Build Lin) <$> mx) $+    mapWithKey_ (\b arr -> f (Build $ Snoc b arr)) Lin t++mapWithKey1 :: (Build1 -> a -> b) -> Radix1Tree a -> Radix1Tree b+mapWithKey1 f = mapWithKey_ (\b arr -> f (Build1 $ b :/ arr)) Lin++{-# INLINE mapWithKey_ #-}+mapWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> b) -> Tsil ByteArray+  -> Radix1Tree a -> Radix1Tree b+mapWithKey_ f = go+  where+    go b t =+      case t of+        Bin p l r     -> Bin p (go b l) (go b r)+        Tip arr mx dx -> Tip arr (f b arr <$> mx) (go (Snoc b arr) dx)+        Nil           -> Nil++++foldl0 :: (b -> a -> b) -> b -> RadixTree a -> b+foldl0 f z (RadixTree mx t) =+  let z' = case mx of+             Just x  -> f z x+             Nothing -> z++  in Data.RadixNTree.Word8.Lazy.foldl1 f z' t++foldl1 :: (b -> a -> b) -> b -> Radix1Tree a -> b+foldl1 f = go+  where+    go z t =+      case t of+        Bin _ l r   -> go (go z l) r++        Tip _ mx dx -> let z' = case mx of+                                  Just x  -> f z x+                                  Nothing -> z++                       in go z' dx++        Nil         -> z++++foldl0' :: (b -> a -> b) -> b -> RadixTree a -> b+foldl0' f z (RadixTree mx t) =+  let !z' = case mx of+              Just x  -> f z x+              Nothing -> z++  in Data.RadixNTree.Word8.Lazy.foldl1' f z' t++foldl1' :: (b -> a -> b) -> b -> Radix1Tree a -> b+foldl1' f = go+  where+    go !z t =+      case t of+        Bin _ l r   -> let !z' = go z l+                       in go z' r++        Tip _ mx dx -> let !z' = case mx of+                                   Just x  -> f z x+                                   Nothing -> z++                       in go z' dx++        Nil         -> z++++foldlWithKey0 :: (b -> Build -> a -> b) -> b -> RadixTree a -> b+foldlWithKey0 f z (RadixTree mx t) =+  let z' = case mx of+             Just x  -> f z (Build Lin) x+             Nothing -> z++  in foldlWithKey_ (\z'' b arr -> f z'' (Build $ Snoc b arr)) z' t++foldlWithKey1 :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey1 f = foldlWithKey_ (\z b arr -> f z (Build1 $ b :/ arr))++{-# INLINE foldlWithKey_ #-}+foldlWithKey_ :: (b -> Tsil ByteArray -> ByteArray -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey_ f = go Lin+  where+    go b z t =+      case t of+        Bin _ l r     -> go b (go b z l) r++        Tip arr mx dx ->+          case mx of+            Nothing -> go (Snoc b arr) z dx+            Just a  -> go (Snoc b arr) (f z b arr a) dx++        Nil           -> z++++foldlWithKey0' :: (b -> Build -> a -> b) -> b -> RadixTree a -> b+foldlWithKey0' f z (RadixTree mx t) =+  let !z' = case mx of+              Just x  -> f z (Build Lin) x+              Nothing -> z++  in foldlWithKey'_ (\z'' b arr -> f z'' (Build $ Snoc b arr)) z' t++foldlWithKey1' :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey1' f = foldlWithKey'_ (\z b arr -> f z (Build1 $ b :/ arr))++{-# INLINE foldlWithKey'_ #-}+foldlWithKey'_ :: (b -> Tsil ByteArray -> ByteArray -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey'_ f = go Lin+  where+    go b !z t =+      case t of+        Bin _ l r     -> let !z' = go b z l+                         in go b z' r++        Tip arr mx dx ->+          case mx of+            Nothing -> go (Snoc b arr) z dx+            Just a  -> let !z' = f z b arr a+                       in go (Snoc b arr) z' dx++        Nil           -> z++++foldr0 :: (a -> b -> b) -> b -> RadixTree a -> b+foldr0 f z (RadixTree mx t) =+  let z' = Data.RadixNTree.Word8.Lazy.foldr1 f z t+  in case mx of+       Just x  -> f x z'+       Nothing -> z'++foldr1 :: (a -> b -> b) -> b -> Radix1Tree a -> b+foldr1 f = go+  where+    go z t =+      case t of+        Bin _ l r   -> go (go z r) l++        Tip _ mx dx -> let z' = go z dx+                       in case mx of+                            Just x  -> f x z'+                            Nothing -> z'++        Nil         -> z++++foldr0' :: (a -> b -> b) -> b -> RadixTree a -> b+foldr0' f z (RadixTree mx t) =+  let !z' = Data.RadixNTree.Word8.Lazy.foldr1' f z t+  in case mx of+       Just x  -> f x z'+       Nothing -> z'++foldr1' :: (a -> b -> b) -> b -> Radix1Tree a -> b+foldr1' f = go+  where+    go !z t =+      case t of+        Bin _ l r   -> let !z' = go z r+                       in go z' l++        Tip _ mx dx -> let !z' = go z dx+                       in case mx of+                            Just x  -> f x z'+                            Nothing -> z'++        Nil         -> z++++foldrWithKey0 :: (Build -> a -> b -> b) -> b -> RadixTree a -> b+foldrWithKey0 f z (RadixTree mx t) =+  let z' = foldrWithKey_ (\b arr -> f (Build $ Snoc b arr)) z t+  in case mx of+       Just x  -> f (Build Lin) x z'+       Nothing -> z'++foldrWithKey1 :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey1 f = foldrWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE foldrWithKey_ #-}+foldrWithKey_ :: (Tsil ByteArray -> ByteArray -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey_ f = go Lin+  where+    go b z t =+      case t of+        Bin _ l r     -> go b (go b z r) l++        Tip arr mx dx -> let z' = go (Snoc b arr) z dx+                         in case mx of+                              Just x  -> f b arr x z'+                              Nothing -> z'++        Nil           -> z++++foldrWithKey0' :: (Build -> a -> b -> b) -> b -> RadixTree a -> b+foldrWithKey0' f z (RadixTree mx t) =+  let !z' = foldrWithKey'_ (\b arr -> f (Build $ Snoc b arr)) z t+  in case mx of+       Just x  -> f (Build Lin) x z'+       Nothing -> z'++foldrWithKey1' :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey1' f = foldrWithKey'_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE foldrWithKey'_ #-}+foldrWithKey'_ :: (Tsil ByteArray -> ByteArray -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey'_ f = go Lin+  where+    go b !z t =+      case t of+        Bin _ l r     -> let !z' = go b z r+                         in go b z' l++        Tip arr mx dx -> let !z' = go (Snoc b arr) z dx+                         in case mx of+                              Just x  -> f b arr x z'+                              Nothing -> z'++        Nil           -> z++++foldMap0 :: Monoid m => (a -> m) -> RadixTree a -> m+foldMap0 f (RadixTree mx t) =+  let m = foldMap1 f t+  in case mx of+       Just x  -> f x <> m+       Nothing -> m++foldMap1 :: Monoid m => (a -> m) -> Radix1Tree a -> m+foldMap1 f = go+  where+    go t =+      case t of+        Bin _ l r   -> go l <> go r++        Tip _ mx dx -> let m = go dx+                       in case mx of+                            Nothing -> m+                            Just a  -> f a <> m++        Nil         -> mempty++++foldMapWithKey0 :: Monoid m => (Build -> a -> m) -> RadixTree a -> m+foldMapWithKey0 f (RadixTree mx t) =+  let m = foldMapWithKey_ (\b arr -> f (Build $ Snoc b arr)) t+  in case mx of+       Just x  -> f (Build Lin) x <> m+       Nothing -> m++foldMapWithKey1 :: Monoid m => (Build1 -> a -> m) -> Radix1Tree a -> m+foldMapWithKey1 f = foldMapWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE foldMapWithKey_ #-}+foldMapWithKey_+  :: Monoid m => (Tsil ByteArray -> ByteArray -> a -> m) -> Radix1Tree a -> m+foldMapWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin _ l r     -> go b l <> go b r++        Tip arr mx dx ->+          let m = go (Snoc b arr) dx+          in case mx of+               Nothing -> m+               Just a  -> f b arr a <> m++        Nil           -> mempty++++traverse0 :: Applicative f => (a -> f b) -> RadixTree a -> f (RadixTree b)+traverse0 f (RadixTree mx t) =+  let dy = traverse1 f t+  in case mx of+       Just x  -> liftA2 RadixTree (Just <$> f x) dy+       Nothing -> RadixTree Nothing <$> dy++traverse1 :: Applicative f => (a -> f b) -> Radix1Tree a -> f (Radix1Tree b)+traverse1 f = go+  where+    go t =+      case t of+        Bin p l r     -> liftA2 (Bin p) (go l) (go r)++        Tip arr mx dx ->+          case mx of+            Nothing -> Tip arr Nothing <$> go dx+            Just x  -> liftA2 (Tip arr . Just) (f x) (go dx)++        Nil           -> pure Nil++++traverseWithKey0 :: Applicative f => (Build -> a -> f b) -> RadixTree a -> f (RadixTree b)+traverseWithKey0 f (RadixTree mx t) =+  let dy = traverseWithKey_ (\b arr -> f (Build $ Snoc b arr)) t+  in case mx of+       Just x  -> liftA2 RadixTree (Just <$> f (Build Lin) x) dy+       Nothing -> RadixTree Nothing <$> dy++traverseWithKey1+  :: Applicative f => (Build1 -> a -> f b) -> Radix1Tree a -> f (Radix1Tree b)+traverseWithKey1 f = traverseWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE traverseWithKey_ #-}+traverseWithKey_+  :: Applicative f+  => (Tsil ByteArray -> ByteArray -> a -> f b) -> Radix1Tree a -> f (Radix1Tree b)+traverseWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> liftA2 (Bin p) (go b l) (go b r)++        Tip arr mx dx ->+          let dy = go (Snoc b arr) dx+          in case mx of+               Nothing -> Tip arr Nothing <$> dy+               Just a  -> liftA2 (Tip arr . Just) (f b arr a) dy++        Nil           -> pure Nil++++{-# INLINE lookup0 #-}+lookup0 :: Feed -> RadixTree a -> Maybe a+lookup0 (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> lookup_ step w z t+      Done     -> mx++{-# INLINE lookup1 #-}+lookup1 :: Feed1 -> Radix1Tree a -> Maybe a+lookup1 (Feed1 w feed) = feed $ \step -> lookup_ step w++{-# INLINE lookup_ #-}+lookup_ :: (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Maybe a+lookup_ step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          go w s $ if w < p+                     then l+                     else r++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  let n' = n + 1+                  in if n' >= sizeofByteArray arr+                       then case step z of+                              More u z' -> go u z' dx+                              Done      -> mx++                       else case step z of+                              More u z' -> goarr u z' n'+                              Done      -> Nothing++              | otherwise = Nothing++        Nil -> Nothing++++{-# INLINE find0 #-}+find0 :: a -> Feed -> RadixTree a -> a+find0 d (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> find_ d step w z t+      Done     -> case mx of+                    Just x  -> x+                    Nothing -> d++{-# INLINE find1 #-}+find1 :: a -> Feed1 -> Radix1Tree a -> a+find1 d (Feed1 w feed) = feed $ \step -> find_ d step w++{-# INLINE find_ #-}+find_ :: a -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> a+find_ d step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          go w s $ if w < p+                     then l+                     else r++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  let n' = n + 1+                  in if n' >= sizeofByteArray arr+                       then case step z of+                              More u z' -> go u z' dx+                              Done      -> case mx of+                                             Just x  -> x+                                             Nothing -> d++                       else case step z of+                              More u z' -> goarr u z' n'+                              Done      -> d++              | otherwise = d++        Nil -> d++++{-# INLINE member0 #-}+member0 :: Feed -> RadixTree a -> Bool+member0 (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> member_ step w z t+      Done     -> case mx of+                    Just _  -> True+                    Nothing -> False++{-# INLINE member1 #-}+member1 :: Feed1 -> Radix1Tree a -> Bool+member1 (Feed1 w feed) = feed $ \step -> member_ step w++{-# INLINE member_ #-}+member_ :: (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Bool+member_ step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          go w s $ if w < p+                     then l+                     else r++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  let n' = n + 1+                  in if n' >= sizeofByteArray arr+                       then case step z of+                              More u z' -> go u z' dx+                              Done      -> case mx of+                                             Just _  -> True+                                             Nothing -> False++                       else case step z of+                              More u z' -> goarr u z' n'+                              Done      -> False++              | otherwise = False++        Nil -> False++++{-# INLINE subtree0 #-}+subtree0 :: Feed -> RadixTree a -> RadixTree a+subtree0 (Feed feed) = \t0@(RadixTree _ t) ->+  feed $ \step s ->+    case step s of+      More w z -> subtree_ step w z t+      Done     -> t0++{-# INLINE subtree1 #-}+subtree1 :: Feed1 -> Radix1Tree a -> RadixTree a+subtree1 (Feed1 w feed) = feed $ \step -> subtree_ step w++{-# INLINE subtree_ #-}+subtree_ :: (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> RadixTree a+subtree_ step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          go w s $ if w < p+                     then l+                     else r++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> go u z' dx+                           Done      -> RadixTree mx dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> let rest = dropTrim (n + 1) arr mx dx+                                        in rest `seq` RadixTree Nothing rest++              | otherwise = RadixTree Nothing Nil++        Nil -> RadixTree Nothing Nil++++{-# INLINE prefix0 #-}+prefix0 :: Feed -> RadixTree a -> RadixTree a+prefix0 (Feed feed) = \t ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree Nothing $ prefix_ step w z t+      Done     -> t++{-# INLINE prefix1 #-}+prefix1 :: Feed1 -> RadixTree a -> Radix1Tree a+prefix1 (Feed1 w feed) =+  feed $ \step -> prefix_ step w++{-# INLINE prefix_ #-}+prefix_ :: (x -> Step Word8 x) -> Word8 -> x -> RadixTree a -> Radix1Tree a+prefix_ step = \w z (RadixTree mx t) ->+  case mx of+    Nothing ->+      case t of+        Bin _ _ _     -> Tip (fromStep step w z) Nothing t+        Tip arr my dy -> Tip (fromStepAppend step w z arr) my dy+        Nil           -> Nil++    Just _  -> Tip (fromStep step w z) mx t++++-- | Current position in the tree.+data Point = -- | Above a node.+             Seam++             -- | In the middle of a 'Tip'.+           | Plane+               {-# UNPACK #-} !Int       -- ^ Always greater than @0@ and smaller than+                                         --   the length of the 'ByteArray'.+               {-# UNPACK #-} !ByteArray++-- | A particular point in the tree.+data Cursor a = -- | This is effectively a 'Tip' where the 'ByteArray' is optional.+                Cursor+                  {-# UNPACK #-} !Point+                  {-# UNPACK #-} !(Maybe a)+                  (Radix1Tree a)++instance Show a => Show (Cursor a) where+  showsPrec d c =+    showParen (d > 10) $+      showString "Cursor " . showsPrec 11 (stop c)++cursor0 :: RadixTree a -> Cursor a+cursor0 (RadixTree mx t) = Cursor Seam mx t++cursor1 :: Radix1Tree a -> Cursor a+cursor1 = Cursor Seam Nothing++{-# INLINE move0 #-}+move0 :: Feed -> Cursor a -> Cursor a+move0 (Feed feed) = \c ->+  feed $ \step s ->+    case step s of+      More w z -> move_ step w z c+      Done     -> c++{-# INLINE move1 #-}+move1 :: Feed1 -> Cursor a -> Cursor a+move1 (Feed1 w feed) = feed $ \step -> move_ step w++{-# INLINE move_ #-}+move_ :: (x -> Step Word8 x) -> Word8 -> x -> Cursor a -> Cursor a+move_ step = \w s (Cursor point mx dx) ->+  case point of+    Seam        -> go w s dx+    Plane i arr -> goarr arr mx dx w s i+  where+    go w s t =+      case t of+        Bin p l r     -> go w s $ if w < p+                                    then l+                                    else r++        Tip brr my dy -> goarr brr my dy w s 0++        Nil           -> Cursor Seam Nothing Nil++    goarr arr mx dx = goarr_+      where+        goarr_ w s n+          | w == indexByteArray arr n =+              let !n' = n + 1+              in case step s of+                   More v z+                     | n' >= sizeofByteArray arr -> go v z dx+                     | otherwise                 -> goarr_ v z n'++                   Done      ->+                     let !point'+                           | n' >= sizeofByteArray arr = Seam+                           | otherwise                 = Plane n' arr++                     in Cursor point' mx dx++          | otherwise = Cursor Seam Nothing Nil++-- | \(\mathcal{O}(1)\).+--   Retrieve the value at which the cursor points.+stop :: Cursor a -> Maybe a+stop (Cursor point mx _) =+  case point of+    Seam -> mx+    _    -> Nothing++-- | \(\mathcal{O}(1)\).+--   Determine whether the cursor points to a point within the tree.+locate :: Cursor a -> Location+locate (Cursor _ Nothing Nil) = Outside+locate _                      = Inside++++{-# INLINE lookupL0 #-}+lookupL0 :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)+lookupL0 openness (Feed feed) (RadixTree mx t) =+  feed $ \step s ->+    case step s of+      More w z ->+        let l = lookupL_ (\b arr -> Lookup (Build $ Snoc b arr)) openness step w z t+        in case l of+             Just _  -> l+             Nothing ->+               case mx of+                 Just x  -> Just $ Lookup (Build Lin) x+                 Nothing -> Nothing++      _        ->+        case openness of+          Open   -> Nothing+          Closed -> case mx of+                      Just x  -> Just $ Lookup (Build Lin) x+                      Nothing -> Nothing++{-# INLINE lookupL1 #-}+lookupL1 :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)+lookupL1 openness (Feed1 w feed) =+  feed $ \step -> lookupL_ (\b arr -> Lookup1 (Build1 (b :/ arr))) openness step w++{-# INLINE lookupL_ #-}+lookupL_+  :: (Tsil ByteArray -> ByteArray -> a -> b)+  -> Openness -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Maybe b+lookupL_ f openness step = go Lin Nothing+  where+    getMax b t =+      let !(# b', arr, a #) = unsafeLookupMaxWithKey_ b t+      in Just $! f b' arr a++    go b getL !w !s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go b getL w s l+                   else getL++            else if w <= upper p+                   then go b (getMax b l) w s r+                   else getMax b r++        Tip arr mx dx -> goarr w s 0+          where+            getThis = f b arr `fmap'` mx++            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          let getL' = getThis <|> getL+                          in case step z of+                               More u z' -> go (Snoc b arr) getL' u z' dx+                               Done      ->+                                 case openness of+                                   Open   -> getL+                                   Closed -> getL'++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> getL++                   LT -> case dx of+                           Nil -> getThis+                           _   -> getMax (Snoc b arr) dx++                   GT -> getL++        Nil -> getL++++{-# INLINE lookupR0 #-}+lookupR0 :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)+lookupR0 openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+        lookupR_ (\b arr -> Lookup (Build $ Snoc b arr)) openness step w z t++      _        ->+        case openness of+          Closed | Just x <- mx -> Just $ Lookup (Build Lin) x++          _      -> case t of+                      Nil -> Nothing+                      _   -> let !(# b, arr, x #) = unsafeLookupMinWithKey_ Lin t+                             in Just $! Lookup (Build $ Snoc b arr) x++{-# INLINE lookupR1 #-}+lookupR1 :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)+lookupR1 openness (Feed1 w feed) =+  feed $ \step -> lookupR_ (\b arr -> Lookup1 (Build1 (b :/ arr))) openness step w++{-# INLINE lookupR_ #-}+lookupR_+  :: (Tsil ByteArray -> ByteArray -> a -> b)+  -> Openness -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Maybe b+lookupR_ f openness step = go Lin Nothing+  where+    getMin b t =+      let !(# b', arr, a #) = unsafeLookupMinWithKey_ b t+      in Just $! f b' arr a++    go b getR w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go b (getMin b r) w s l+                   else getMin b l++            else if w <= upper p+                   then go b getR w s r+                   else getR++        Tip arr mx dx -> goarr w s 0+          where+            getThis = f b arr `fmap'` mx++            getBelow =+              case dx of+                Nil -> Nothing+                _   -> getMin (Snoc b arr) dx++            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> go (Snoc b arr) getR u z' dx+                            Done      ->+                                  ( case openness of+                                      Open   -> getBelow+                                      Closed -> getThis <|> getBelow+                                  )+                              <|> getR++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> (getThis <|> getBelow) <|> getR++                   GT -> getThis <|> getBelow++                   LT -> getR++        Nil -> getR++++{-# INLINE adjustL0 #-}+adjustL0 :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustL0 f openness (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree (f <$> mx) $ adjustL_ f openness step w z t+      Done     ->+        case openness of+          Open   -> t0+          Closed -> case mx of+                      Just x  -> RadixTree (Just $ f x) t+                      Nothing -> t0++{-# INLINE adjustL1 #-}+adjustL1 :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustL1 f openness (Feed1 w feed) =+  feed $ \step -> adjustL_ f openness step w++{-# INLINE adjustL_ #-}+adjustL_+  :: (a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustL_ f openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go w s l) r+                   else t++            else if w <= upper p+                   then Bin p (map1 f l) (go w s r)+                   else map1 f t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr (f <$> mx) $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f <$> mx++                              in Tip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   LT -> map1 f t++                   GT -> t++        Nil -> Nil++++{-# INLINE adjustLWithKey0 #-}+adjustLWithKey0 :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustLWithKey0 f openness (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree (f (Build Lin) <$> mx) $+                    adjustLWithKey_ (\b arr -> f (Build $ Snoc b arr)) openness step w z t+      Done     ->+        case openness of+          Open   -> t0+          Closed -> RadixTree (f (Build Lin) <$> mx) t++{-# INLINE adjustLWithKey1 #-}+adjustLWithKey1 :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustLWithKey1 f openness (Feed1 w feed) =+  feed $ \step -> adjustLWithKey_ (\b arr -> f (Build1 $ b :/ arr)) openness step w++{-# INLINE adjustLWithKey_ #-}+adjustLWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustLWithKey_ f openness step = go Lin+  where+    go b w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go b w s l) r+                   else t++            else if w <= upper p+                   then Bin p (mapWithKey_ f b l) (go b w s r)+                   else mapWithKey_ f b t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr (f b arr <$> mx) $+                                           go (Snoc b arr) u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f b arr <$> mx++                              in Tip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   LT -> mapWithKey_ f b t++                   GT -> t++        Nil -> Nil++++{-# INLINE adjustR0 #-}+adjustR0 :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustR0 f openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ adjustR_ f openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> f <$> mx++        in RadixTree my (map1 f t)++{-# INLINE adjustR1 #-}+adjustR1 :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustR1 f openness (Feed1 w feed) =+  feed $ \step -> adjustR_ f openness step w++{-# INLINE adjustR_ #-}+adjustR_+  :: (a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustR_ f openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go w s l) (map1 f r)+                   else map1 f t++            else if w <= upper p+                   then Bin p l (go w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr mx $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f <$> mx++                              in Tip arr my $ map1 f dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> map1 f t++                   GT -> map1 f t++                   LT -> t++        Nil -> Nil++++{-# INLINE adjustRWithKey0 #-}+adjustRWithKey0 :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustRWithKey0 f openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+       RadixTree mx $+         adjustRWithKey_ (\b arr -> f (Build $ Snoc b arr)) openness step w z t++      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> f (Build Lin) <$> mx++        in RadixTree my $ mapWithKey_ (\b arr -> f (Build $ Snoc b arr)) Lin t++{-# INLINE adjustRWithKey1 #-}+adjustRWithKey1 :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustRWithKey1 f openness (Feed1 w feed) =+  feed $ \step -> adjustRWithKey_ (\b arr -> f (Build1 $ b :/ arr)) openness step w++{-# INLINE adjustRWithKey_ #-}+adjustRWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustRWithKey_ f openness step = go Lin+  where+    go b w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go b w s l) (mapWithKey_ f b r)+                   else mapWithKey_ f b t++            else if w <= upper p+                   then Bin p l (go b w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr mx $ go (Snoc b arr) u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f b arr <$> mx++                              in Tip arr my $ mapWithKey_ f (Snoc b arr) dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> mapWithKey_ f b t++                   GT -> mapWithKey_ f b t++                   LT -> t++        Nil -> Nil++++{-# INLINE updateL0 #-}+updateL0 :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateL0 f openness (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree (f =<< mx) $ updateL_ f openness step w z t+      Done     ->+        case openness of+          Open   -> t0+          Closed -> RadixTree (f =<< mx) t++{-# INLINE updateL1 #-}+updateL1 :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateL1 f openness (Feed1 w feed) =+  feed $ \step -> updateL_ f openness step w++{-# INLINE updateL_ #-}+updateL_+  :: (a -> Maybe a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+updateL_ f openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go w s l) r+                   else t++            else if w <= upper p+                   then rebin p (mapMaybe1 f l) (go w s r)+                   else mapMaybe1 f t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr (f =<< mx) $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f =<< mx++                              in retip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   LT -> mapMaybe1 f t++                   GT -> t++        Nil -> Nil++++{-# INLINE updateLWithKey0 #-}+updateLWithKey0+  :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateLWithKey0 f openness (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+        RadixTree (f (Build Lin) =<< mx) $+          updateLWithKey_ (\b arr -> f (Build $ Snoc b arr)) openness step w z t++      Done     ->+        case openness of+          Open   -> t0+          Closed -> RadixTree (f (Build Lin) =<< mx) t++{-# INLINE updateLWithKey1 #-}+updateLWithKey1+  :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateLWithKey1 f openness (Feed1 w feed) =+  feed $ \step -> updateLWithKey_ (\b arr -> f (Build1 $ b :/ arr)) openness step w++{-# INLINE updateLWithKey_ #-}+updateLWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Maybe a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+updateLWithKey_ f openness step = go Lin+  where+    go b w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go b w s l) r+                   else t++            else if w <= upper p+                   then rebin p (mapMaybeWithKey_ f b l) (go b w s r)+                   else mapMaybeWithKey_ f b t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr (f b arr =<< mx) $+                                           go (Snoc b arr) u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f b arr =<< mx++                              in retip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   LT -> mapMaybeWithKey_ f b t++                   GT -> t++        Nil -> Nil++++{-# INLINE updateR0 #-}+updateR0 :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateR0 f openness (Feed feed) (RadixTree mx t) =+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ updateR_ f openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> f =<< mx++        in RadixTree my (mapMaybe1 f t)++{-# INLINE updateR1 #-}+updateR1 :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateR1 f openness (Feed1 w feed) =+  feed $ \step -> updateR_ f openness step w++{-# INLINE updateR_ #-}+updateR_+  :: (a -> Maybe a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+updateR_ f openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebin p (go w s l) (mapMaybe1 f r)+                   else mapMaybe1 f t++            else if w <= upper p+                   then rebinR p l (go w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr mx $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f =<< mx++                              in retip arr my $ mapMaybe1 f dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> mapMaybe1 f t++                   GT -> mapMaybe1 f t++                   LT -> t++        Nil -> Nil++++{-# INLINE updateRWithKey0 #-}+updateRWithKey0+  :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateRWithKey0 f openness (Feed feed) (RadixTree mx t) =+  feed $ \step s ->+    case step s of+      More w z ->+        RadixTree mx $+          updateRWithKey_ (\b arr -> f (Build $ Snoc b arr)) openness step w z t++      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> f (Build Lin) =<< mx++        in RadixTree my (mapMaybeWithKey_ (\b arr -> f (Build $ Snoc b arr)) Lin t)++{-# INLINE updateRWithKey1 #-}+updateRWithKey1+  :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateRWithKey1 f openness (Feed1 w feed) =+  feed $ \step -> updateRWithKey_ (\b arr -> f (Build1 $ b :/ arr)) openness step w++{-# INLINE updateRWithKey_ #-}+updateRWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Maybe a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+updateRWithKey_ f openness step = go Lin+  where+    go b w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebin p (go b w s l) (mapMaybeWithKey_ f b r)+                   else mapMaybeWithKey_ f b t++            else if w <= upper p+                   then rebinR p l (go b w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr mx $ go (Snoc b arr) u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f b arr =<< mx++                              in retip arr my $ mapMaybeWithKey_ f (Snoc b arr) dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> mapMaybeWithKey_ f b t++                   GT -> mapMaybeWithKey_ f b t++                   LT -> t++        Nil -> Nil++++{-# INLINE takeL0 #-}+takeL0 :: Openness -> Feed -> RadixTree a -> RadixTree a+takeL0 openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ takeL_ openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> Nothing+                   Closed -> mx++        in RadixTree my Nil++{-# INLINE takeL1 #-}+takeL1 :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+takeL1 openness (Feed1 w0 feed) = feed $ \step -> takeL_ openness step w0++{-# INLINE takeL_ #-}+takeL_ :: Openness -> (x -> Step Prefix x) -> Prefix -> x -> Radix1Tree a -> Radix1Tree a+takeL_ openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go w s l+                   else Nil++            else if w <= upper p+                   then rebinR p l (go w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr mx $ go u z' dx+                            Done      ->+                              case openness of+                                Open   -> Nil+                                Closed -> retip arr mx Nil++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> Nil++                   LT -> t++                   GT -> Nil++        Nil -> Nil++++{-# INLINE takeR0 #-}+takeR0 :: Openness -> Feed -> RadixTree a -> RadixTree a+takeR0 openness (Feed feed) (RadixTree mx t) =+  feed $ \step s ->+    case step s of+      More w z -> RadixTree Nothing $ takeR_ openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> Nothing+                   Closed -> mx++        in RadixTree my t++{-# INLINE takeR1 #-}+takeR1 :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+takeR1 openness (Feed1 w0 feed) = feed $ \step -> takeR_ openness step w0++{-# INLINE takeR_ #-}+takeR_ :: Openness -> (x -> Step Prefix x) -> Prefix -> x -> Radix1Tree a -> Radix1Tree a+takeR_ openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go w s l) r+                   else t++            else if w <= upper p+                   then go w s r+                   else Nil++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr Nothing $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> Nothing+                                         Closed -> mx++                              in retip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   GT -> t++                   LT -> Nil++        Nil -> Nil++++type UBin a = (# Prefix, Radix1Tree a, Radix1Tree a #)++type UTip a = (# Key, Int, ByteArray, Maybe a, Radix1Tree a #)++++union0 :: RadixTree a -> RadixTree a -> RadixTree a+union0 (RadixTree mA tA) (RadixTree mB tB) = RadixTree (mA <|> mB) (union1 tA tB)++union1 :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+union1 = anyAny+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA    -> binAny (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> tB++    tipAny uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip uA tA uB tB lenA+                                else tipTip uB tB uA tA lenB++        Nil             | nA == 0   -> tA+                        | otherwise -> Tip (dropByteArray nA arrA) mA dA++    tipTip (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then Tip arrA' (mA <|> mB) (anyAny dA dB)+                             else Tip arrA' mA $+                                    tipAny (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | o == 1 =+              let !tA' | nA == 0   = tA+                       | otherwise = Tip (dropByteArray nA arrA) mA dA++                  !tB' | nB == 0   = tB+                       | otherwise = Tip (dropByteArray nB arrB) mB dB++              in join wA tA' wB tB'++          | otherwise =+              let !o' = o - 1++                  !(# !arrC, !arrA' #) = splitByteArray nA o' arrA++                  !arrB' = dropByteArray (nB + o') arrB++              in Tip arrC Nothing $ join wA (Tip arrA' mA dA)+                                         wB (Tip arrB' mB dB)++    binAny uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0+                           in tipBin (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> tA++    tipBin uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = let !tA' | nA == 0   = tA+                                | otherwise = Tip (dropByteArray nA arrA) mA dA++                       in join wA tA' pB tB++      | wA < pB      = Bin pB (tipAny uA tA lB) rB+      | otherwise    = Bin pB lB (tipAny uA tA rB)++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = join pA tA pB tB++      in case Prelude.compare pA pB of+           EQ                  -> Bin pA (anyAny lA lB) (anyAny rA rB)++           LT | pB <= upper pA -> Bin pA lA (binAny uB tB rA)+              | pA >= lower pB -> Bin pB (binAny uA tA lB) rB+              | otherwise      -> no++           GT | pA <= upper pB -> Bin pB lB (binAny uA tA rB)+              | pB >= lower pA -> Bin pA (binAny uB tB lA) rA+              | otherwise      -> no++++unionL0 :: RadixTree a -> RadixTree a -> RadixTree a+unionL0 (RadixTree mA tA) (RadixTree mB tB) = RadixTree (mA <|> mB) (unionL1 tA tB)++unionL1 :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionL1 =+  union_ $ \s a b ->+    let !(# c #) = case s of+                     L -> (# a #)+                     R -> (# b #)+    in Just c+++unionWith0 :: (a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a+unionWith0 f (RadixTree mA tA) (RadixTree mB tB) =+  let mC = case mA of+             Just a  -> case mB of+                          Just b  -> Just $ f a b+                          Nothing -> mA++             Nothing -> mB++  in RadixTree mC (unionWith1 f tA tB)++unionWith1 :: (a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionWith1 f =+  union_ $ \s a b ->+    let !(# c #) = case s of+                     L -> (# f a b #)+                     R -> (# f b a #)+    in Just c++++{-# INLINE union_ #-}+union_+  :: (forall x y. S x y a a -> x -> y -> Maybe a)+  -> Radix1Tree a+  -> Radix1Tree a+  -> Radix1Tree a+union_ f = anyAny L+  where+    anyAny s tA tB =+      case tA of+        Bin pA lA rA    -> binAny s (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> tB++    tipAny s uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s uA tA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' uB tB uA tA lenB++        Nil             | nA == 0   -> tA+                        | otherwise -> Tip (dropByteArray nA arrA) mA dA++    tipTip s (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC = case mA of+                                             Just a  -> case mB of+                                                          Just b  -> f s a b+                                                          Nothing -> mA++                                             Nothing -> mB++                                  in Tip arrA' mC (anyAny s dA dB)++                             else Tip arrA' mA $+                                    let !(# s' #) = other s+                                    in tipAny s' (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | o == 1 =+              let !tA' | nA == 0   = tA+                       | otherwise = Tip (dropByteArray nA arrA) mA dA++                  !tB' | nB == 0   = tB+                       | otherwise = Tip (dropByteArray nB arrB) mB dB++              in join wA tA' wB tB'++          | otherwise =+              let !o' = o - 1++                  !(# !arrC, !arrA' #) = splitByteArray nA o' arrA++                  !arrB' = dropByteArray (nB + o') arrB++              in Tip arrC Nothing $ join wA (Tip arrA' mA dA)+                                         wB (Tip arrB' mB dB)++    binAny s uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> tA++    tipBin s uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = let !tA' | nA == 0   = tA+                                | otherwise = Tip (dropByteArray nA arrA) mA dA++                       in join wA tA' pB tB++      | wA < pB      = Bin pB (tipAny s uA tA lB) rB+      | otherwise    = Bin pB lB (tipAny s uA tA rB)++    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = join pA tA pB tB++      in case Prelude.compare pA pB of+           EQ                  -> Bin pA (anyAny s lA lB) (anyAny s rA rB)++           LT | pB <= upper pA -> let !(# s' #) = other s+                                  in Bin pA lA (binAny s' uB tB rA)+              | pA >= lower pB -> Bin pB (binAny s uA tA lB) rB+              | otherwise      -> no++           GT | pA <= upper pB -> Bin pB lB (binAny s uA tA rB)+              | pB >= lower pA -> let !(# s' #) = other s+                                  in Bin pA (binAny s' uB tB lA) rA+              | otherwise      -> no+++++unionWithKey0 :: (Build -> a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a+unionWithKey0 f (RadixTree mA tA) (RadixTree mB tB) =+  let mC = case mA of+             Just a  -> case mB of+                          Just b  -> Just $ f (Build Lin) a b+                          Nothing -> mA++             Nothing -> mB++  in RadixTree mC $ unionWithKey_+                      ( \s b arr vA vB ->+                           let b0 = Build $ Snoc b arr++                               !(# c #) = case s of+                                            L -> (# f b0 vA vB #)+                                            R -> (# f b0 vB vA #)++                           in Just c+                      )+                      tA tB++unionWithKey1 :: (Build1 -> a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionWithKey1 f =+  unionWithKey_ $ \s b arr vA vB ->+    let b1 = Build1 $ b :/ arr++        !(# c #) = case s of+                     L -> (# f b1 vA vB #)+                     R -> (# f b1 vB vA #)+    in Just c++{-# INLINE unionWithKey_ #-}+unionWithKey_+  :: (forall x y. S x y a a -> Tsil ByteArray -> ByteArray -> x -> y -> Maybe a)+  -> Radix1Tree a+  -> Radix1Tree a+  -> Radix1Tree a+unionWithKey_ f = anyAny L Lin+  where+    anyAny s b tA tB =+      case tA of+        Bin pA lA rA    -> binAny s b (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s b (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> tB++    tipAny s b uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s b uA tA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' b uB tB uA tA lenB++        Nil             | nA == 0   -> tA+                        | otherwise -> Tip (dropByteArray nA arrA) mA dA++    tipTip s b (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC =+                                        case mA of+                                          Just xA ->+                                            case mB of+                                              Just xB -> f s b arrA' xA xB+                                              Nothing -> mA++                                          Nothing -> mB++                                  in Tip arrA' mC (anyAny s (Snoc b arrA') dA dB)++                             else Tip arrA' mA $+                                    let !(# s' #) = other s+                                    in tipAny s' (Snoc b arrA')+                                         (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | o == 1 =+              let !tA' | nA == 0   = tA+                       | otherwise = Tip (dropByteArray nA arrA) mA dA++                  !tB' | nB == 0   = tB+                       | otherwise = Tip (dropByteArray nB arrB) mB dB++              in join wA tA' wB tB'++          | otherwise =+              let !o' = o - 1++                  !(# !arrC, !arrA' #) = splitByteArray nA o' arrA++                  !arrB' = dropByteArray (nB + o') arrB++              in Tip arrC Nothing $ join wA (Tip arrA' mA dA)+                                         wB (Tip arrB' mB dB)++    binAny s b uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' b (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> tA++    tipBin s b uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = let !tA' | nA == 0   = tA+                                | otherwise = Tip (dropByteArray nA arrA) mA dA++                       in join wA tA' pB tB++      | wA < pB      = Bin pB (tipAny s b uA tA lB) rB+      | otherwise    = Bin pB lB (tipAny s b uA tA rB)++    binBin s b uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = join pA tA pB tB++      in case Prelude.compare pA pB of+           EQ                  -> Bin pA (anyAny s b lA lB) (anyAny s b rA rB)++           LT | pB <= upper pA -> let !(# s' #) = other s+                                  in Bin pA lA (binAny s' b uB tB rA)+              | pA >= lower pB -> Bin pB (binAny s b uA tA lB) rB+              | otherwise      -> no++           GT | pA <= upper pB -> Bin pB lB (binAny s b uA tA rB)+              | pB >= lower pA -> let !(# s' #) = other s+                                  in Bin pA (binAny s' b uB tB lA) rA+              | otherwise      -> no++++difference0 :: RadixTree a -> RadixTree b -> RadixTree a+difference0 (RadixTree mA tA) (RadixTree mB tB) =+  let mC = case mB of+             Just _  -> Nothing+             Nothing -> mA++  in RadixTree mC $ difference1 tA tB++difference1 :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a+difference1 =+  difference_ $ \_ _ _ ->+    Nothing+++differenceWith0+  :: (a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a+differenceWith0 f (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just xA <- mA, Just xB <- mB = f xA xB+         | otherwise                    = mA++  in RadixTree mC $ differenceWith1 f tA tB++differenceWith1+  :: (a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a+differenceWith1 f =+  difference_ $ \s xA xB ->+    case s of+      L -> f xA xB+      R -> f xB xA++{-# INLINE difference_ #-}+difference_+  :: (forall x y. S x y a b -> x -> y -> Maybe a)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree a+difference_ (f :: forall n o. S n o x y -> n -> o -> Maybe x) = anyAny L+  where+    anyAny :: forall a b. S a b x y -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    anyAny s tA tB =+      case tA of+        Bin pA lA rA    -> binAny s (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> case s of+                             L -> Nil+                             R -> tB++    tipAny+      :: forall a b. S a b x y -> UTip a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    tipAny s uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s uA tA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' uB tB uA tA lenB++        Nil             -> case s of+                             L | nA == 0   -> tA+                               | otherwise -> Tip (dropByteArray nA arrA) mA dA++                             R -> Nil++    tipTip+      :: forall a b. S a b x y+      -> UTip a -> Radix1Tree a -> UTip b -> Radix1Tree b -> Int -> Radix1Tree x+    tipTip s (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC | Just xA <- mA, Just xB <- mB = f s xA xB+                                         | otherwise =+                                             case s of+                                               L -> mA+                                               R -> mB++                                  in retip arrA' mC (anyAny s dA dB)++                             else let mA' = case s of+                                              L -> mA+                                              R -> Nothing++                                  in retip arrA' mA' $+                                       let !(# s' #) = other s+                                       in tipAny s' (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise =+              case s of+                L | nA == 0   -> tA+                  | otherwise -> Tip (dropByteArray nA arrA) mA dA++                R | nB == 0   -> tB+                  | otherwise -> Tip (dropByteArray nB arrB) mB dB++    binAny+      :: forall a b. S a b x y -> UBin a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> case s of+                             L -> tA+                             R -> tB++    tipBin+      :: forall a b. S a b x y+      -> UTip a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree x+    tipBin s uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = case s of+                         L | nA == 0   -> tA+                           | otherwise -> Tip (dropByteArray nA arrA) mA dA++                         R -> tB++      | wA < pB      = case s of+                         L -> tipAny s uA tA lB+                         R -> rebinL pB (tipAny s uA tA lB) rB++      | otherwise    = case s of+                         L -> tipAny s uA tA rB+                         R -> rebinR pB lB (tipAny s uA tA rB)++    binBin+      :: forall a b. S a b x y+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree x+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let no = case s of+                 L -> tA+                 R -> tB++      in case Prelude.compare pA pB of+           EQ                  -> rebin pA (anyAny s lA lB) (anyAny s rA rB)++           LT | pB <= upper pA -> case s of+                                    L -> rebinR pA lA (binAny R uB tB rA)+                                    R -> binAny L uB tB rA++              | pA >= lower pB -> case s of+                                    L -> binAny s uA tA lB+                                    R -> rebinL pB (binAny s uA tA lB) rB++              | otherwise      -> no++           GT | pA <= upper pB -> case s of+                                    L -> binAny s uA tA rB+                                    R -> rebinR pB lB (binAny s uA tA rB)++              | pB >= lower pA -> case s of+                                    L -> rebinL pA (binAny R uB tB lA) rA+                                    R -> binAny L uB tB lA++              | otherwise      -> no++++differenceWithKey0+  :: (Build -> a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a+differenceWithKey0 f (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just xA <- mA, Just xB <- mB = f (Build Lin) xA xB+         | otherwise                    = mA++  in RadixTree mC $ differenceWithKey_+                      ( \s b arr xA xB ->+                           let b0 = Build $ Snoc b arr+                           in case s of+                                L -> f b0 xA xB+                                R -> f b0 xB xA+                      )+                      tA tB++differenceWithKey1+  :: (Build1 -> a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a+differenceWithKey1 f =+  differenceWithKey_ $ \s b arr xA xB ->+    let b1 = Build1 $ b :/ arr+    in case s of+         L -> f b1 xA xB+         R -> f b1 xB xA++{-# INLINE differenceWithKey_ #-}+differenceWithKey_+  :: (forall x y. S x y a b -> Tsil ByteArray -> ByteArray -> x -> y -> Maybe a)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree a+differenceWithKey_+  (f :: forall n o. S n o x y -> Tsil ByteArray -> ByteArray -> n -> o -> Maybe x) =+    anyAny L Lin+  where+    anyAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    anyAny s b tA tB =+      case tA of+        Bin pA lA rA    -> binAny s b (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s b (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> case s of+                             L -> Nil+                             R -> tB++    tipAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    tipAny s b uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s b uA tA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' b uB tB uA tA lenB++        Nil             -> case s of+                             L | nA == 0   -> tA+                               | otherwise -> Tip (dropByteArray nA arrA) mA dA++                             R -> Nil++    tipTip+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> UTip b -> Radix1Tree b -> Int -> Radix1Tree x+    tipTip s b (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC | Just xA <- mA, Just xB <- mB =+                                             f s b arrA' xA xB++                                         | otherwise =+                                             case s of+                                               L -> mA+                                               R -> mB++                                  in retip arrA' mC (anyAny s (Snoc b arrA') dA dB)++                             else let mA' = case s of+                                              L -> mA+                                              R -> Nothing++                                  in retip arrA' mA' $+                                       let !(# s' #) = other s+                                       in tipAny s' (Snoc b arrA')+                                            (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise =+              case s of+                L | nA == 0   -> tA+                  | otherwise -> Tip (dropByteArray nA arrA) mA dA++                R | nB == 0   -> tB+                  | otherwise -> Tip (dropByteArray nB arrB) mB dB++    binAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    binAny s b uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' b (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> case s of+                             L -> tA+                             R -> tB++    tipBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree x+    tipBin s b uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = case s of+                         L | nA == 0   -> tA+                           | otherwise -> Tip (dropByteArray nA arrA) mA dA++                         R -> tB++      | wA < pB      = case s of+                         L -> tipAny s b uA tA lB+                         R -> rebinL pB (tipAny s b uA tA lB) rB++      | otherwise    = case s of+                         L -> tipAny s b uA tA rB+                         R -> rebinR pB lB (tipAny s b uA tA rB)++    binBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree x+    binBin s b uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let no = case s of+                 L -> tA+                 R -> tB++      in case Prelude.compare pA pB of+           EQ                  -> rebin pA (anyAny s b lA lB) (anyAny s b rA rB)++           LT | pB <= upper pA -> case s of+                                    L -> rebinR pA lA (binAny R b uB tB rA)+                                    R -> binAny L b uB tB rA++              | pA >= lower pB -> case s of+                                    L -> binAny s b uA tA lB+                                    R -> rebinL pB (binAny s b uA tA lB) rB++              | otherwise      -> no++           GT | pA <= upper pB -> case s of+                                    L -> binAny s b uA tA rB+                                    R -> rebinR pB lB (binAny s b uA tA rB)++              | pB >= lower pA -> case s of+                                    L -> rebinL pA (binAny R b uB tB lA) rA+                                    R -> binAny L b uB tB lA++              | otherwise      -> no++++compare0 :: (a -> b -> Bool) -> RadixTree a -> RadixTree b -> PartialOrdering+compare0 f (RadixTree mA tA) (RadixTree mB tB) =+  let o = case mA of+            Just xA -> case mB of+                         Just xB+                           | f xA xB   -> Equal+                           | otherwise -> Incomparable++                         Nothing -> Superset++            Nothing -> case mB of+                         Just _  -> Subset+                         Nothing -> Equal++  in order o $ Data.RadixNTree.Word8.Lazy.compare1 f tA tB++compare1 :: (a -> b -> Bool) -> Radix1Tree a -> Radix1Tree b -> PartialOrdering+compare1 (f :: x -> y -> Bool) = anyAny L+  where+    anyAny :: forall a b. S a b x y -> Radix1Tree a -> Radix1Tree b -> PartialOrdering+    anyAny s tA tB =+      case tA of+        Bin pA lA rA    -> binAny s (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> case tB of+                             Nil -> Equal+                             _   -> case s of+                                      L -> Subset+                                      R -> Superset++    tipAny+      :: forall a b. S a b x y -> UTip a -> Radix1Tree a -> Radix1Tree b -> PartialOrdering+    tipAny s uA@(# _, nA, arrA, _, _ #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s uA tA (# pB, lB, rB #)++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s uA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' uB uA tA lenB++        Nil             -> case s of+                             L -> Superset+                             R -> Subset++    tipTip+      :: forall a b. S a b x y -> UTip a -> UTip b -> Radix1Tree b -> Int -> PartialOrdering+    tipTip s (# wA0, nA, arrA, mA, dA #) (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then if nB' == sizeofByteArray arrB+                          then let o_ = case mA of+                                          Just xA -> case mB of+                                                       Just xB ->+                                                         let eq = case s of+                                                                    L -> f xA xB+                                                                    R -> f xB xA++                                                         in if eq+                                                              then Equal+                                                              else Incomparable++                                                       Nothing -> case s of+                                                                    L -> Superset+                                                                    R -> Subset+                                          Nothing -> case mB of+                                                       Just _  -> case s of+                                                                    L -> Subset+                                                                    R -> Superset++                                                       Nothing -> Equal++                               in order o_ $ anyAny s dA dB++                          else let !(# s' #) = other s+                               in tipAny s' (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise = case s of+                             L -> Superset+                             R -> Subset++    binAny+      :: forall a b. S a b x y -> UBin a -> Radix1Tree a -> Radix1Tree b -> PartialOrdering+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' (# wB, 0, arrB, mB, dB #) tB uA++        Nil             -> case s of+                             L -> Superset+                             R -> Subset++    tipBin :: forall a b. S a b x y -> UTip a -> Radix1Tree a -> UBin b -> PartialOrdering+    tipBin s uA@(# wA, _, _, _, _ #) tA (# pB, lB, rB #)+      | beyond pB wA = Incomparable+      | otherwise    = limit s . tipAny s uA tA $ if wA < pB+                                                     then lB+                                                     else rB++    binBin+      :: forall a b. S a b x y+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> PartialOrdering+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> order (anyAny s lA lB) (anyAny s rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s+                               in limit s' $ binAny s' uB tB rA+           | pA >= lower pB -> limit s $ binAny s uA tA lB+           | otherwise      -> Incomparable++        GT | pA <= upper pB -> limit s $ binAny s uA tA rB+           | pB >= lower pA -> let !(# s' #) = other s+                               in limit s' $ binAny s' uB tB lA+           | otherwise      -> Incomparable++++disjoint0 :: RadixTree a -> RadixTree b -> Bool+disjoint0 (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just _ <- mA, Just _ <- mB = False+         | otherwise                  = True++  in mC && disjoint1 tA tB++disjoint1 :: Radix1Tree a -> Radix1Tree b -> Bool+disjoint1 = anyAny+  where+    anyAny :: forall a b. Radix1Tree a -> Radix1Tree b -> Bool+    anyAny tA tB =+      case tA of+        Bin pA lA rA    -> binAny (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> True++    tipAny :: forall a b. UTip a -> Radix1Tree a -> Radix1Tree b -> Bool+    tipAny uA@(# _, nA, arrA, _, _ #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin uA tA (# pB, lB, rB #)++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip uA uB tB lenA++                                else tipTip uB uA tA lenB++        Nil             -> True++    tipTip :: forall a b. UTip a -> UTip b -> Radix1Tree b -> Int -> Bool+    tipTip (# wA0, nA, arrA, mA, dA #) (# wB0, nB, arrB, mB, dB #) tB len = go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then if nB' == sizeofByteArray arrB+                          then let mC | Just _ <- mA, Just _ <- mB = False+                                      | otherwise                  = True++                               in mC && anyAny dA dB++                          else tipAny (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise = True++    binAny :: forall a b. UBin a -> Radix1Tree a -> Radix1Tree b -> Bool+    binAny uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                           in tipBin (# wB, 0, arrB, mB, dB #) tB uA++        Nil             -> True++    tipBin :: forall a b. UTip a -> Radix1Tree a -> UBin b -> Bool+    tipBin uA@(# wA, _, _, _, _ #) tA (# pB, lB, rB #)+      | beyond pB wA = True+      | otherwise    = tipAny uA tA $ if wA < pB+                                        then lB+                                        else rB++    binBin :: forall a b. UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Bool+    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> anyAny lA lB && anyAny rA rB++        LT | pB <= upper pA -> binAny uB tB rA+           | pA >= lower pB -> binAny uA tA lB+           | otherwise      -> True++        GT | pA <= upper pB -> binAny uA tA rB+           | pB >= lower pA -> binAny uB tB lA+           | otherwise      -> True++++intersection0 :: RadixTree a -> RadixTree a -> RadixTree a+intersection0 (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just _ <- mA, Just _ <- mB = mA+         | otherwise                  = Nothing++  in RadixTree mC (intersection1 tA tB)++intersection1 :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+intersection1 = anyAny+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA    -> binAny (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> Nil++    tipAny uA@(# _, nA, arrA, _, _ #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin uA tA (# pB, lB, rB #)++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip uA uB tB lenA++                                else tipTip uB uA tA lenB++        Nil             -> Nil++    tipTip (# wA0, nA, arrA, mA, dA #) (# wB0, nB, arrB, mB, dB #) tB len = go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC | Just _ <- mA, Just _ <- mB = mA+                                         | otherwise                  = Nothing++                                  in retip arrA' mC (anyAny dA dB)++                             else retip arrA' Nothing $+                                    tipAny (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise = Nil++    binAny uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                           in tipBin (# wB, 0, arrB, mB, dB #) tB uA++        Nil             -> Nil++    tipBin uA@(# wA, _, _, _, _ #) tA (# pB, lB, rB #)+      | beyond pB wA = Nil+      | otherwise    = tipAny uA tA $ if wA < pB+                                        then lB+                                        else rB++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny lA lB) (anyAny rA rB)++        LT | pB <= upper pA -> binAny uB tB rA+           | pA >= lower pB -> binAny uA tA lB+           | otherwise      -> Nil++        GT | pA <= upper pB -> binAny uA tA rB+           | pB >= lower pA -> binAny uB tB lA+           | otherwise      -> Nil++++intersectionL0 :: RadixTree a -> RadixTree b -> RadixTree a+intersectionL0 (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just _ <- mA, Just _ <- mB = mA+         | otherwise                  = Nothing++  in RadixTree mC (intersectionL1 tA tB)++intersectionL1 :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a+intersectionL1 =+  intersection_ $ \s a b ->+    let !(# c #) = case s of+                     L -> (# a #)+                     R -> (# b #)+    in Just c+++intersectionWith0 :: (a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c+intersectionWith0 f (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just a <- mA, Just b <- mB = Just $ f a b+         | otherwise                  = Nothing++  in RadixTree mC (intersectionWith1 f tA tB)++intersectionWith1 :: (a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+intersectionWith1 f =+  intersection_ $ \s a b ->+    let !(# c #) = case s of+                     L -> (# f a b #)+                     R -> (# f b a #)+    in Just c++{-# INLINE intersection_ #-}+intersection_+  :: (forall x y. S x y a b -> x -> y -> Maybe c)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree c+intersection_ (f :: forall n o. S n o x y -> n -> o -> Maybe c) = anyAny L+  where+    anyAny :: forall a b. S a b x y -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    anyAny s tA tB =+      case tA of+        Bin pA lA rA    -> binAny s (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> Nil++    tipAny+      :: forall a b. S a b x y -> UTip a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    tipAny s uA@(# _, nA, arrA, _, _ #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s uA tA (# pB, lB, rB #)++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s uA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' uB uA tA lenB++        Nil             -> Nil++    tipTip+      :: forall a b. S a b x y -> UTip a -> UTip b -> Radix1Tree b -> Int -> Radix1Tree c+    tipTip s (# wA0, nA, arrA, mA, dA #) (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC | Just xA <- mA, Just xB <- mB = f s xA xB+                                         | otherwise                    = Nothing++                                  in retip arrA' mC (anyAny s dA dB)++                             else retip arrA' Nothing $+                                    let !(# s' #) = other s+                                    in tipAny s' (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise = Nil++    binAny+      :: forall a b. S a b x y -> UBin a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' (# wB, 0, arrB, mB, dB #) tB uA++        Nil             -> Nil++    tipBin :: forall a b. S a b x y -> UTip a -> Radix1Tree a -> UBin b -> Radix1Tree c+    tipBin s uA@(# wA, _, _, _, _ #) tA (# pB, lB, rB #)+      | beyond pB wA = Nil+      | otherwise    = tipAny s uA tA $ if wA < pB+                                          then lB+                                          else rB++    binBin+      :: forall a b. S a b x y+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree c+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny s lA lB) (anyAny s rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s+                               in binAny s' uB tB rA+           | pA >= lower pB -> binAny s uA tA lB+           | otherwise      -> Nil++        GT | pA <= upper pB -> binAny s uA tA rB+           | pB >= lower pA -> let !(# s' #) = other s+                               in binAny s' uB tB lA+           | otherwise      -> Nil++++intersectionWithKey0+  :: (Build -> a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c+intersectionWithKey0 f (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just a <- mA, Just b <- mB = Just $ f (Build Lin) a b+         | otherwise                  = Nothing++  in RadixTree mC $ intersectionWithKey_+                      ( \s b arr vA vB ->+                           let b0 = Build $ Snoc b arr++                               !(# c #) = case s of+                                            L -> (# f b0 vA vB #)+                                            R -> (# f b0 vB vA #)++                           in Just c+                      )+                      tA tB++intersectionWithKey1+  :: (Build1 -> a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+intersectionWithKey1 f =+  intersectionWithKey_ $ \s b arr vA vB ->+    let b1 = Build1 $ b :/ arr++        !(# c #) = case s of+                     L -> (# f b1 vA vB #)+                     R -> (# f b1 vB vA #)++    in Just c++{-# INLINE intersectionWithKey_ #-}+intersectionWithKey_+  :: (forall x y. S x y a b -> Tsil ByteArray -> ByteArray -> x -> y -> Maybe c)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree c+intersectionWithKey_+  (f :: forall n o. S n o x y -> Tsil ByteArray -> ByteArray -> n -> o -> Maybe c) =+    anyAny L Lin+  where+    anyAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    anyAny s b tA tB =+      case tA of+        Bin pA lA rA    -> binAny s b (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s b (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> Nil++    tipAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    tipAny s b uA@(# _, nA, arrA, _, _ #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s b uA tA (# pB, lB, rB #)++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s b uA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' b uB uA tA lenB++        Nil             -> Nil++    tipTip+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> UTip b -> Radix1Tree b -> Int -> Radix1Tree c+    tipTip s b (# wA0, nA, arrA, mA, dA #) (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC | Just xA <- mA, Just xB <- mB =+                                             f s b arrA' xA xB++                                         | otherwise                    = Nothing+++                                  in retip arrA' mC (anyAny s (Snoc b arrA') dA dB)++                             else retip arrA' Nothing $+                                    let !(# s' #) = other s+                                    in tipAny s' (Snoc b arrA')+                                         (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise = Nil++    binAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    binAny s b uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' b (# wB, 0, arrB, mB, dB #) tB uA++        Nil             -> Nil++    tipBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> UBin b -> Radix1Tree c+    tipBin s b uA@(# wA, _, _, _, _ #) tA (# pB, lB, rB #)+      | beyond pB wA = Nil+      | otherwise    = tipAny s b uA tA $ if wA < pB+                                            then lB+                                            else rB++    binBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree c+    binBin s b uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny s b lA lB) (anyAny s b rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s+                               in binAny s' b uB tB rA+           | pA >= lower pB -> binAny s b uA tA lB+           | otherwise      -> Nil++        GT | pA <= upper pB -> binAny s b uA tA rB+           | pB >= lower pA -> let !(# s' #) = other s+                               in binAny s' b uB tB lA+           | otherwise      -> Nil++++{-# INLINE merge0 #-}+merge0+  :: (Build -> a -> b -> Maybe c)+  -> (Build -> a -> Maybe c)+  -> (Build -> Radix1Tree a -> Radix1Tree c)+  -> (Build -> b -> Maybe c)+  -> (Build -> Radix1Tree b -> Radix1Tree c)+  -> RadixTree a+  -> RadixTree b+  -> RadixTree c+merge0 f oneX treeX oneY treeY = \(RadixTree mA tA) (RadixTree mB tB) ->+  let mC = case mA of+             Just xA -> case mB of+                          Just xB -> f (Build Lin) xA xB+                          Nothing -> oneX (Build Lin) xA++             Nothing -> case mB of+                          Just xB -> oneY (Build Lin) xB+                          Nothing -> Nothing++  in RadixTree mC $+       merge_ (\b arr -> f (Build $ Snoc b arr))+         (\b arr -> oneX (Build $ Snoc b arr)) treeX+         (\b arr -> oneY (Build $ Snoc b arr)) treeY+         tA tB++{-# INLINE merge1 #-}+merge1+  :: (Build1 -> a -> b -> Maybe c)+  -> (Build1 -> a -> Maybe c)+  -> (Build -> Radix1Tree a -> Radix1Tree c)+  -> (Build1 -> b -> Maybe c)+  -> (Build -> Radix1Tree b -> Radix1Tree c)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree c+merge1 f oneX treeX oneY treeY =+  merge_ (\b arr -> f (Build1 $ b :/ arr))+    (\b arr -> oneX (Build1 $ b :/ arr)) treeX+    (\b arr -> oneY (Build1 $ b :/ arr)) treeY++{-# INLINE merge_ #-}+merge_+  :: (Tsil ByteArray -> ByteArray -> a -> b -> Maybe c)+  -> (Tsil ByteArray -> ByteArray -> a -> Maybe c)+  -> (Build -> Radix1Tree a -> Radix1Tree c)+  -> (Tsil ByteArray -> ByteArray -> b -> Maybe c)+  -> (Build -> Radix1Tree b -> Radix1Tree c)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree c+merge_ (f :: Tsil ByteArray -> ByteArray -> x -> y -> Maybe c) oneX treeX oneY treeY =+  anyAny L Lin+  where+    sideA :: forall a b. S a b x y -> Tsil ByteArray -> Radix1Tree a -> Radix1Tree c+    sideA s b tA = case s of+                     L -> treeX (Build b) tA+                     R -> treeY (Build b) tA++    sideB :: forall a b. S a b x y -> Tsil ByteArray -> Radix1Tree b -> Radix1Tree c+    sideB s b tB = case s of+                     L -> treeY (Build b) tB+                     R -> treeX (Build b) tB++    anyAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    anyAny s b tA tB =+      case tA of+        Bin pA lA rA    -> binAny s b (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s b (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> sideB s b tB++    tipAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    tipAny s b uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s b uA tA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' b uB tB uA tA lenB++        Nil             -> sideA s b $ if nA == 0+                                         then tA+                                         else Tip (dropByteArray nA arrA) mA dA++    tipTip+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> UTip b -> Radix1Tree b -> Int -> Radix1Tree c+    tipTip s b (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC = case mA of+                                             Just xA ->+                                               case mB of+                                                 Just xB -> case s of+                                                              L -> f b arrA' xA xB+                                                              R -> f b arrA' xB xA++                                                 Nothing -> case s of+                                                              L -> oneX b arrA' xA+                                                              R -> oneY b arrA' xA++                                             Nothing ->+                                               case mB of+                                                 Just xB -> case s of+                                                              L -> oneY b arrA' xB+                                                              R -> oneX b arrA' xB++                                                 Nothing -> Nothing++                                  in retip arrA' mC (anyAny s (Snoc b arrA') dA dB)++                             else let mC = case mA of+                                             Just xA -> case s of+                                                          L -> oneX b arrA' xA+                                                          R -> oneY b arrA' xA++                                             Nothing -> Nothing++                                  in retip arrA' mC $+                                       let !(# s' #) = other s+                                       in tipAny s' (Snoc b arrA')+                                            (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | o == 1 =+              safeJoin wA ( sideA s b $ if nA == 0+                                          then tA+                                          else Tip (dropByteArray nA arrA) mA dA+                          )+                       wB ( sideB s b $ if nB == 0+                                          then tB+                                          else Tip (dropByteArray nB arrB) mB dB+                          )++          | otherwise =+              let !o' = o - 1++                  !(# !arrC, !arrA' #) = splitByteArray nA o' arrA++                  !arrB' = dropByteArray (nB + o') arrB++              in retip arrC Nothing $ safeJoin wA (sideA s b $ Tip arrA' mA dA)+                                               wB (sideB s b $ Tip arrB' mB dB)++    binAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    binAny s b uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' b (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> sideA s b tA++    tipBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree c+    tipBin s b uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = safeJoin wA (sideA s b $ if nA == 0+                                                  then tA+                                                  else Tip (dropByteArray nA arrA) mA dA+                                   )+                                pB (sideB s b tB)++      | wA < pB      = rebin pB (tipAny s b uA tA lB) (sideB s b rB)++      | otherwise    = rebin pB (sideB s b lB) (tipAny s b uA tA rB)++    binBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree c+    binBin s b uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = safeJoin pA (sideA s b tA) pB (sideB s b tB)++      in case Prelude.compare pA pB of+           EQ                  -> rebin pA (anyAny s b lA lB) (anyAny s b rA rB)++           LT | pB <= upper pA -> let !(# s' #) = other s++                                  in rebin pA (sideA s b lA) (binAny s' b uB tB rA)++              | pA >= lower pB -> rebin pB (binAny s b uA tA lB) (sideB s b rB)++              | otherwise      -> no++           GT | pA <= upper pB -> rebin pB (sideB s b lB) (binAny s b uA tA rB)++              | pB >= lower pA -> let !(# s' #) = other s++                                  in rebin pA (binAny s' b uB tB lA) (sideA s b rA)++              | otherwise      -> no++++{-# INLINE insert0 #-}+insert0 :: Feed -> a -> RadixTree a -> RadixTree a+insert0 (Feed feed) a = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ insert_ a step w z t+      Done     -> RadixTree (Just a) t++{-# INLINE insert1 #-}+insert1 :: Feed1 -> a -> Radix1Tree a -> Radix1Tree a+insert1 (Feed1 w feed) a =+  feed $ \step -> insert_ a step w++{-# INLINE insert_ #-}+insert_ :: a -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+insert_ a step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> join+                            w (singleton_ step w s a)+                            p t++          | w < p      -> Bin p (go w s l) r+          | otherwise  -> Bin p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> Tip arr mx (go u z' dx)+                           Done      -> Tip arr (Just a) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      ->+                             let !(# !brr, !crr #) = splitByteArray 0 (n + 1) arr+                             in Tip brr (Just a) (Tip crr mx dx)++              | n == 0    =+                  join+                    (indexByteArray arr 0) t+                    w (singleton_ step w s a)++              | otherwise =+                  let !(# !brr, !crr #) = splitByteArray 0 n arr+                  in Tip brr Nothing $+                       join+                         (indexByteArray crr 0) (Tip crr mx dx)+                         v (singleton_ step v z a)++        Nil -> singleton_ step w s a++++{-# INLINE insertWith0 #-}+insertWith0 :: (a -> a) -> Feed -> a -> RadixTree a -> RadixTree a+insertWith0 f (Feed feed) a = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ insertWith_ f a step w z t+      Done     ->+        let y = case mx of+                  Just x  -> f x+                  Nothing -> a++        in RadixTree (Just y) t++{-# INLINE insertWith1 #-}+insertWith1 :: (a -> a) -> Feed1 -> a -> Radix1Tree a -> Radix1Tree a+insertWith1 f (Feed1 w feed) a =+  feed $ \step -> insertWith_ f a step w++{-# INLINE insertWith_ #-}+insertWith_+  :: (a -> a) -> a -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+insertWith_ f a step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> join+                            w (singleton_ step w s a)+                            p t++          | w < p      -> Bin p (go w s l) r+          | otherwise  -> Bin p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> Tip arr mx (go u z' dx)+                           Done      -> let y = case mx of+                                                  Just x  -> f x+                                                  Nothing -> a++                                        in Tip arr (Just y) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      ->+                             let !(# !brr, !crr #) = splitByteArray 0 (n + 1) arr+                             in Tip brr (Just a) (Tip crr mx dx)++              | n == 0    =+                  join+                    (indexByteArray arr 0) t+                    w (singleton_ step w s a)++              | otherwise =+                  let !(# !brr, !crr #) = splitByteArray 0 n arr+                  in Tip brr Nothing $+                       join+                         (indexByteArray crr 0) (Tip crr mx dx)+                         v (singleton_ step v z a)++        Nil -> singleton_ step w s a++++{-# INLINE adjust0 #-}+adjust0 :: (a -> a) -> Feed -> RadixTree a -> RadixTree a+adjust0 f (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ adjust_ f step w z t+      Done     -> RadixTree (fmap f mx) t++{-# INLINE adjust1 #-}+adjust1 :: (a -> a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjust1 f (Feed1 w feed) =+  feed $ \step -> adjust_ f step w++{-# INLINE adjust_ #-}+adjust_ :: (a -> a) -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjust_ f step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> Bin p (go w s l) r+          | otherwise  -> Bin p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> Tip arr mx (go u z' dx)+                           Done      -> Tip arr (fmap f mx) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> t++              | otherwise = t++        Nil -> t++++{-# INLINE delete0 #-}+delete0 :: Feed -> RadixTree a -> RadixTree a+delete0 (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ delete_ step w z t+      Done     -> RadixTree Nothing t++{-# INLINE delete1 #-}+delete1 :: Feed1 -> Radix1Tree a -> Radix1Tree a+delete1 (Feed1 w feed) =+  feed $ \step -> delete_ step w++{-# INLINE delete_ #-}+delete_ :: (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+delete_ step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> rebinL p (go w s l) r+          | otherwise  -> rebinR p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> retip arr mx (go u z' dx)+                           Done      -> retip arr Nothing dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> t++              | otherwise = t++        Nil          -> t++++{-# INLINE prune0 #-}+prune0 :: Openness -> Feed -> RadixTree a -> RadixTree a+prune0 openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ prune_ openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> Nothing++        in RadixTree my Nil++{-# INLINE prune1 #-}+prune1 :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+prune1 openness (Feed1 w feed) =+  feed $ \step -> prune_ openness step w++{-# INLINE prune_ #-}+prune_ :: Openness -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+prune_ openness step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> rebinL p (go w s l) r+          | otherwise  -> rebinR p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> retip arr mx (go u z' dx)+                           Done      ->+                             case openness of+                               Open   -> retip arr mx Nil+                               Closed -> Nil++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> Nil++              | otherwise = t++        Nil          -> t++++{-# INLINE update0 #-}+update0 :: (a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a+update0 f (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ update_ f step w z t+      Done     -> RadixTree (f =<< mx) t++{-# INLINE update1 #-}+update1 :: (a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+update1 f (Feed1 w feed) =+  feed $ \step -> update_ f step w++{-# INLINE update_ #-}+update_+  :: (a -> Maybe a) -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+update_ f step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> rebinL p (go w s l) r+          | otherwise  -> rebinR p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> retip arr mx (go u z' dx)+                           Done      -> retip arr (f =<< mx) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> t++              | otherwise = t++        Nil         -> t++++{-# INLINE alter0 #-}+alter0 :: (Maybe a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a+alter0 f (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ alter_ f step w z t+      Done     -> RadixTree (f mx) t++{-# INLINE alter1 #-}+alter1 :: (Maybe a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+alter1 f (Feed1 w feed) =+  feed $ \step -> alter_ f step w++{-# INLINE alter_ #-}+alter_+  :: (Maybe a -> Maybe a)+  -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+alter_ f step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> case f Nothing of+                            Nothing -> t+                            Just a  -> join+                                         w (singleton_ step w s a)+                                         p t++          | w < p      -> rebinL p (go w s l) r+          | otherwise  -> rebinR p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> retip arr mx (go u z' dx)+                           Done      -> retip arr (f mx) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      ->+                             case f Nothing of+                               Nothing -> t+                               Just a  ->+                                 let !(# !brr, !crr #) = splitByteArray 0 (n + 1) arr+                                 in Tip brr (Just a) (Tip crr mx dx)++              | otherwise =+                  case f Nothing of+                    Nothing -> t+                    Just a  ->+                      if n == 0+                        then join+                               (indexByteArray arr 0) (Tip arr mx dx)+                               w (singleton_ step v z a)++                        else let !(# !brr, !crr #) = splitByteArray 0 n arr+                             in Tip brr Nothing $+                                  join+                                    (indexByteArray crr 0) (Tip crr mx dx)+                                    v (singleton_ step v z a)++        Nil       ->+          case f Nothing of+            Nothing -> t+            Just a  -> singleton_ step w s a++++{-# INLINE shape0 #-}+shape0 :: (RadixTree a -> RadixTree a) -> Feed -> RadixTree a -> RadixTree a+shape0 f (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ shape_ f step w z t+      Done     -> f t0++{-# INLINE shape1 #-}+shape1 :: (RadixTree a -> RadixTree a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+shape1 f (Feed1 w feed) =+  feed $ \step -> shape_ f step w++{-# INLINE shape_ #-}+shape_+  :: (RadixTree a -> RadixTree a)+  -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+shape_ f step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> let !(RadixTree my dy) = f (RadixTree Nothing Nil)+                          in case retip (fromStep step w s) my dy of+                               Nil -> t+                               dz  -> join+                                        w dz+                                        p t++          | w < p      -> rebinL p (go w s l) r+          | otherwise  -> rebinR p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  let n' = n + 1+                  in if n' >= sizeofByteArray arr+                       then case step z of+                              More u z' -> retip arr mx (go u z' dx)+                              Done      -> let !(RadixTree my dy) = f (RadixTree mx dx)+                                           in retip arr my dy++                       else case step z of+                              More u z' -> goarr u z' n'+                              Done      ->+                                let !(# !brr, !crr #) = splitByteArray 0 n' arr++                                    !(RadixTree my dy) = f (RadixTree Nothing (Tip crr mx dx))++                                in retip brr my dy++              | otherwise =+                  let !(RadixTree my dy) = f (RadixTree Nothing Nil)+                  in case retip (fromStep step v z) my dy of+                       Nil -> t+                       dz  ->+                         if n == 0+                           then join+                                  (indexByteArray arr 0) (Tip arr mx dx)+                                  v dz++                           else let !(# !brr, !crr #) = splitByteArray 0 n arr+                                in Tip brr Nothing $+                                     join+                                       (indexByteArray crr 0) (Tip crr mx dx)+                                       v dz++        Nil       ->+          let !(RadixTree my dy) = f (RadixTree Nothing Nil)+          in retip (fromStep step w s) my dy++++{-# INLINE splitL0 #-}+splitL0 :: Openness -> Feed -> RadixTree a -> (RadixTree a, RadixTree a)+splitL0 openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+        let !(# l, r #) = splitL_ openness step w z t+        in (RadixTree mx l, RadixTree Nothing r)++      Done     ->+        let !(# my, mz #) = case openness of+                              Open   -> (# Nothing, mx #)+                              Closed -> (# mx, Nothing #)++        in (RadixTree my Nil, RadixTree mz t)++{-# INLINE splitL1 #-}+splitL1 :: Openness -> Feed1 -> Radix1Tree a -> (Radix1Tree a, Radix1Tree a)+splitL1 openness (Feed1 w feed) = \t ->+  feed $ \step s ->+    case splitL_ openness step w s t of+      (# l, r #) -> (l, r)++{-# INLINE splitL_ #-}+splitL_+  :: Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> (# Radix1Tree a, Radix1Tree a #)+splitL_ openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then let !(# ll, lr #) = go w s l+                        in (# ll, rebinL p lr r #)++                   else (# Nil, t #)++            else if w <= upper p+                   then let !(# rl, rr #) = go w s r+                        in (# rebinR p l rl, rr #)++                   else (# t, Nil #)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' ->+                              let !(# dl, dr #) = go u z' dx+                              in (# retip arr mx dl, retip arr Nothing dr #)++                            Done      ->+                              let !(# my, mz #) =+                                    case openness of+                                      Open   -> (# Nil             , mx      #)+                                      Closed -> (# retip arr mx Nil, Nothing #)++                              in (# my, retip arr mz dx #)++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> (# Nil, t #)++                   LT -> (# t, Nil #)++                   GT -> (# Nil, t #)++        Nil -> (# Nil, Nil #)++++{-# INLINE splitLookup0 #-}+splitLookup0 :: Feed -> RadixTree a -> (RadixTree a, Maybe a, RadixTree a)+splitLookup0 (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+        let !(# l, my, r #) = splitLookup_ step w z t+        in (RadixTree mx l, my, RadixTree Nothing r)++      Done     -> (RadixTree Nothing Nil, mx, RadixTree Nothing t)++{-# INLINE splitLookup1 #-}+splitLookup1 :: Feed1 -> Radix1Tree a -> (Radix1Tree a, Maybe a, Radix1Tree a)+splitLookup1 (Feed1 w feed) = \t ->+  feed $ \step s ->+    case splitLookup_ step w s t of+      (# l, mx, r #) -> (l, mx, r)++{-# INLINE splitLookup_ #-}+splitLookup_+  :: (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> (# Radix1Tree a, Maybe a, Radix1Tree a #)+splitLookup_ step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then let !(# ll, my, lr #) = go w s l+                        in (# ll, my, rebinL p lr r #)++                   else (# Nil, Nothing, t #)++            else if w <= upper p+                   then let !(# rl, my, rr #) = go w s r+                        in (# rebinR p l rl, my, rr #)++                   else (# t, Nothing, Nil #)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' ->+                              let !(# dl, my, dr #) = go u z' dx+                              in (# retip arr mx dl, my, retip arr Nothing dr #)++                            Done      ->+                              (# Nil, mx, retip arr Nothing dx #)++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> (# Nil, Nothing, t #)++                   LT -> (# t, Nothing, Nil #)++                   GT -> (# Nil, Nothing, t #)++        Nil -> (# Nil, Nothing, Nil #)++++{-# INLINE filterMaybe #-}+filterMaybe :: (a -> Bool) -> Maybe a -> Maybe a+filterMaybe f mx =+  case mx of+    Just x | f x -> Just x+    _            -> Nothing++filter0 :: (a -> Bool) -> RadixTree a -> RadixTree a+filter0 f (RadixTree mx t) = RadixTree (filterMaybe f mx) (filter1 f t)++filter1 :: (a -> Bool) -> Radix1Tree a -> Radix1Tree a+filter1 f = go+  where+    go t =+      case t of+        Bin p l r     -> rebin p (go l) (go r)+        Tip arr mx dx -> retip arr (filterMaybe f mx) (go dx)+        Nil           -> Nil++++filterWithKey0 :: (Build -> a -> Bool) -> RadixTree a -> RadixTree a+filterWithKey0 f (RadixTree mx t) =+  RadixTree (filterMaybe (f (Build Lin)) mx) $+    filterWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++filterWithKey1 :: (Build1 -> a -> Bool) -> Radix1Tree a -> Radix1Tree a+filterWithKey1 f = filterWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE filterWithKey_ #-}+filterWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Bool) -> Radix1Tree a -> Radix1Tree a+filterWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> rebin p (go b l) (go b r)++        Tip arr mx dx -> retip arr (filterMaybe (f b arr) mx) (go (Snoc b arr) dx)++        Nil           -> Nil++++mapMaybe0 :: (a -> Maybe b) -> RadixTree a -> RadixTree b+mapMaybe0 f (RadixTree mx t) = RadixTree (f =<< mx) (mapMaybe1 f t)++mapMaybe1 :: (a -> Maybe b) -> Radix1Tree a -> Radix1Tree b+mapMaybe1 f = go+  where+    go t =+      case t of+        Bin p l r     -> rebin p (go l) (go r)+        Tip arr mx dx -> retip arr (f =<< mx) (go dx)+        Nil           -> Nil++++mapMaybeWithKey0 :: (Build -> a -> Maybe b) -> RadixTree a -> RadixTree b+mapMaybeWithKey0 f (RadixTree mx t) =+  RadixTree (f (Build Lin) =<< mx) $+    mapMaybeWithKey_ (\b arr -> f (Build $ Snoc b arr)) Lin t++mapMaybeWithKey1 :: (Build1 -> a -> Maybe b) -> Radix1Tree a -> Radix1Tree b+mapMaybeWithKey1 f = mapMaybeWithKey_ (\b arr -> f (Build1 $ b :/ arr)) Lin++{-# INLINE mapMaybeWithKey_ #-}+mapMaybeWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Maybe b) -> Tsil ByteArray+  -> Radix1Tree a -> Radix1Tree b+mapMaybeWithKey_ f = go+  where+    go b t =+      case t of+        Bin p l r     -> rebin p (go b l) (go b r)++        Tip arr mx dx -> retip arr (f b arr =<< mx) (go (Snoc b arr) dx)++        Nil           -> Nil++++partition0 :: (a -> Bool) -> RadixTree a -> (RadixTree a, RadixTree a)+partition0 f = \(RadixTree mx t) ->+  let !(# l, r #) = partition_ f t++      !(# my, mz #) =+        case mx of+          Just x+            | f x       -> (# mx     , Nothing #)+            | otherwise -> (# Nothing, mx      #)++          Nothing       -> (# Nothing, Nothing #)++  in (RadixTree my l, RadixTree mz r)++partition1 :: (a -> Bool) -> Radix1Tree a -> (Radix1Tree a, Radix1Tree a)+partition1 f = \t ->+  case partition_ f t of+    (# l, r #) -> (l, r)++partition_ :: (a -> Bool) -> Radix1Tree a -> (# Radix1Tree a, Radix1Tree a #)+partition_ f = go+  where+    go t =+      case t of+        Bin p l r   ->+          let !(# ly, lz #) = go l+              !(# ry, rz #) = go r++          in (# rebin p ly ry, rebin p lz rz #)++        Tip arr mx dx ->+          let !(# dy, dz #) = go dx+          in case mx of+               Nothing -> (# retip arr Nothing dy, retip arr Nothing dz #)+               Just x  ->+                 if f x+                   then (# Tip   arr (Just x) dy, retip arr Nothing  dz #)+                   else (# retip arr Nothing  dy, Tip   arr (Just x) dz #)++        Nil         -> (# Nil, Nil #)++++partitionWithKey0 :: (Build -> a -> Bool) -> RadixTree a -> (RadixTree a, RadixTree a)+partitionWithKey0 f = \(RadixTree mx t) ->+  let !(# l, r #) = partitionWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++      !(# my, mz #) =+        case mx of+          Just x+            | f (Build Lin) x -> (# mx     , Nothing #)+            | otherwise       -> (# Nothing, mx      #)++          Nothing             -> (# Nothing, Nothing #)++  in (RadixTree my l, RadixTree mz r)++partitionWithKey1 :: (Build1 -> a -> Bool) -> Radix1Tree a -> (Radix1Tree a, Radix1Tree a)+partitionWithKey1 f = \t ->+  case partitionWithKey_ (\b arr -> f (Build1 $ b :/ arr)) t of+    (# !l, !r #) -> (l, r)++{-# INLINE partitionWithKey_ #-}+partitionWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Bool)+  -> Radix1Tree a -> (# Radix1Tree a, Radix1Tree a #)+partitionWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     ->+          let !(# ly, lz #) = go b l+              !(# ry, rz #) = go b r++          in (# rebin p ly ry, rebin p lz rz #)++        Tip arr mx dx ->+          let !(# dy, dz #) = go (Snoc b arr) dx+          in case mx of+               Nothing -> (# retip arr Nothing dy, retip arr Nothing dz #)+               Just x  ->+                 if f b arr x+                   then (# Tip   arr (Just x) dy, retip arr Nothing  dz #)+                   else (# retip arr Nothing  dy, Tip   arr (Just x) dz #)++        Nil         -> (# Nil, Nil #)++++mapEither0 :: (a -> Either b c) -> RadixTree a -> (RadixTree b, RadixTree c)+mapEither0 f = \(RadixTree mx t) ->+  let !(# l, r #) = mapEither_ f t++      !(# my, mz #) =+        case mx of+          Just x ->+            case f x of+              Left y  -> (# Just y , Nothing #)+              Right z -> (# Nothing, Just z  #)++          Nothing     -> (# Nothing, Nothing #)++  in (RadixTree my l, RadixTree mz r)++mapEither1 :: (a -> Either b c) -> Radix1Tree a -> (Radix1Tree b, Radix1Tree c)+mapEither1 f = \t ->+  case mapEither_ f t of+    (# l, r #) -> (l, r)++mapEither_ :: (a -> Either b c) -> Radix1Tree a -> (# Radix1Tree b, Radix1Tree c #)+mapEither_ f = go+  where+    go t =+      case t of+        Bin p l r     ->+          let !(# ly, lz #) = go l+              !(# ry, rz #) = go r++          in (# rebin p ly ry, rebin p lz rz #)++        Tip arr mx dx ->+          let !(# dy, dz #) = go dx+          in case mx of+               Nothing -> (# retip arr Nothing dy, retip arr Nothing dz #)+               Just x  ->+                 case f x of+                   Left y  -> (# Tip   arr (Just y) dy, retip arr Nothing  dz #)+                   Right z -> (# retip arr Nothing  dy, Tip   arr (Just z) dz #)++        Nil         -> (# Nil, Nil #)++++mapEitherWithKey0+  :: (Build -> a -> Either b c) -> RadixTree a -> (RadixTree b, RadixTree c)+mapEitherWithKey0 f = \(RadixTree mx t) ->+  let !(# l, r #) = mapEitherWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++      !(# my, mz #) =+        case mx of+          Just x ->+            case f (Build Lin) x of+              Left y  -> (# Just y , Nothing #)+              Right z -> (# Nothing, Just z  #)++          Nothing     -> (# Nothing, Nothing #)++  in (RadixTree my l, RadixTree mz r)++mapEitherWithKey1+  :: (Build1 -> a -> Either b c) -> Radix1Tree a -> (Radix1Tree b, Radix1Tree c)+mapEitherWithKey1 f = \t ->+  case mapEitherWithKey_ (\b arr -> f (Build1 $ b :/ arr)) t of+    (# l, r #) -> (l, r)++{-# INLINE mapEitherWithKey_ #-}+mapEitherWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Either b c)+  -> Radix1Tree a -> (# Radix1Tree b, Radix1Tree c #)+mapEitherWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     ->+          let !(# ly, lz #) = go b l+              !(# ry, rz #) = go b r++          in (# rebin p ly ry, rebin p lz rz #)++        Tip arr mx dx ->+          let !(# dy, dz #) = go (Snoc b arr) dx+          in case mx of+               Nothing -> (# retip arr Nothing dy, retip arr Nothing dz #)+               Just x  ->+                 case f b arr x of+                   Left y  -> (# Tip   arr (Just y) dy, retip arr Nothing  dz #)+                   Right z -> (# retip arr Nothing  dy, Tip   arr (Just z) dz #)++        Nil         -> (# Nil, Nil #)++++moduleLoc1 :: String+moduleLoc1 = "Radix1Tree.Word8.Lazy"++++lookupMin0 :: RadixTree a -> Maybe a+lookupMin0 (RadixTree mx t) =+  case mx of+    Just x  -> Just x+    Nothing -> lookupMin1 t++lookupMin1 :: Radix1Tree a -> Maybe a+lookupMin1 Nil = Nothing+lookupMin1 t   = let !(# a #) = unsafeLookupMin1 t+                 in Just a++unsafeLookupMin1 :: Radix1Tree a -> (# a #)+unsafeLookupMin1 t =+  case t of+    Bin _ l _   -> unsafeLookupMin1 l+    Tip _ mx dx -> case mx of+                     Just x  -> (# x #)+                     Nothing -> unsafeLookupMin1 dx++    Nil         -> throw $ MalformedTree moduleLoc1 "lookupMin"++++lookupMinWithKey0 :: RadixTree a -> Maybe (Lookup a)+lookupMinWithKey0 (RadixTree mx t) =+  case mx of+    Just x  -> Just (Lookup (Build Lin) x)+    Nothing ->+      case t of+        Nil -> Nothing+        _   -> let !(# b, arr, a #) = unsafeLookupMinWithKey_ Lin t+               in Just $! Lookup (Build $ Snoc b arr) a++lookupMinWithKey1 :: Radix1Tree a -> Maybe (Lookup1 a)+lookupMinWithKey1 Nil = Nothing+lookupMinWithKey1 t   = Just $! unsafeLookupMinWithKey1 t++unsafeLookupMinWithKey1 :: Radix1Tree a -> Lookup1 a+unsafeLookupMinWithKey1 t =+  let !(# b, arr, a #) = unsafeLookupMinWithKey_ Lin t+  in Lookup1 (Build1 $ b :/ arr) a++unsafeLookupMinWithKey_+  :: Tsil ByteArray -> Radix1Tree a -> (# Tsil ByteArray, ByteArray, a #)+unsafeLookupMinWithKey_ = go+  where+    go b t =+      case t of+        Bin _ l _     -> go b l+        Tip arr mx dx -> case mx of+                           Just x  -> (# b, arr, x #)+                           Nothing -> go (Snoc b arr) dx++        Nil           -> throw $ MalformedTree moduleLoc1 "lookupMinWithKey"++++lookupMax0 :: RadixTree a -> Maybe a+lookupMax0 (RadixTree mx t) =+  case t of+    Nil -> mx+    _   -> let !(# a #) = unsafeLookupMax1 t+           in Just a++lookupMax1 :: Radix1Tree a -> Maybe a+lookupMax1 Nil = Nothing+lookupMax1 t   = let !(# a #) = unsafeLookupMax1 t+                 in Just a++unsafeLookupMax1 :: Radix1Tree a -> (# a #)+unsafeLookupMax1 t =+  case t of+    Bin _ _ r   -> unsafeLookupMax1 r+    Tip _ mx dx -> case dx of+                     Nil | Just x <- mx -> (# x #)+                     _                  -> unsafeLookupMax1 dx++    Nil         -> throw $ MalformedTree moduleLoc1 "lookupMin"++++lookupMaxWithKey0 :: RadixTree a -> Maybe (Lookup a)+lookupMaxWithKey0 (RadixTree mx t) =+  case t of+    Nil -> Lookup (Build Lin) `fmap'` mx+    _   -> let !(# b, arr, a #) = unsafeLookupMaxWithKey_ Lin t+           in Just $! Lookup (Build $ Snoc b arr) a++lookupMaxWithKey1 :: Radix1Tree a -> Maybe (Lookup1 a)+lookupMaxWithKey1 Nil = Nothing+lookupMaxWithKey1 t   = Just $! unsafeLookupMaxWithKey1 t++unsafeLookupMaxWithKey1 :: Radix1Tree a -> Lookup1 a+unsafeLookupMaxWithKey1 t =+  let !(# b, arr, a #) = unsafeLookupMaxWithKey_ Lin t+  in Lookup1 (Build1 $ b :/ arr) a++unsafeLookupMaxWithKey_+  :: Tsil ByteArray -> Radix1Tree a -> (# Tsil ByteArray, ByteArray, a #)+unsafeLookupMaxWithKey_ = go+  where+    go b t =+      case t of+        Bin _ _ r     -> go b r+        Tip arr mx dx -> case dx of+                           Nil | Just x <- mx -> (# b, arr, x #)+                           _                  -> go (Snoc b arr) dx++        Nil           -> throw $ MalformedTree moduleLoc1 "lookupMaxWithKey"++++deleteMin0 :: RadixTree a -> RadixTree a+deleteMin0 (RadixTree mx t) =+  case mx of+    Just _  -> RadixTree Nothing t+    Nothing -> RadixTree mx (deleteMin1 t)++deleteMin1 :: Radix1Tree a -> Radix1Tree a+deleteMin1 Nil = Nil+deleteMin1 r   = unsafeDeleteMin1 r++unsafeDeleteMin1 :: Radix1Tree a -> Radix1Tree a+unsafeDeleteMin1 = go+  where+    go t =+      case t of+        Bin p l r     -> rebinL p (go l) r++        Tip arr mx dx -> case mx of+                           Nothing -> retip arr mx (go dx)+                           Just _  -> retip arr Nothing dx++        Nil           -> Nil++++deleteMax0 :: RadixTree a -> RadixTree a+deleteMax0 t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just _  -> RadixTree Nothing t+             Nothing -> t0++    _   -> RadixTree mx (unsafeDeleteMax1 t)++deleteMax1 :: Radix1Tree a -> Radix1Tree a+deleteMax1 Nil = Nil+deleteMax1 r   = unsafeDeleteMax1 r++unsafeDeleteMax1 :: Radix1Tree a -> Radix1Tree a+unsafeDeleteMax1 = go+  where+    go t =+      case t of+        Bin p l r     -> rebinR p l (go r)++        Tip arr mx dx -> case dx of+                           Nil     -> Nil+                           _       -> retip arr mx (go dx)++        Nil           -> Nil++++adjustMin0 :: (a -> a) -> RadixTree a -> RadixTree a+adjustMin0 f (RadixTree mx t) =+  case mx of+    Just x  -> RadixTree (Just $ f x) t+    Nothing -> RadixTree mx (adjustMin1 f t)++adjustMin1 :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMin1 _ Nil = Nil+adjustMin1 f r   = unsafeAdjustMin1 f r++unsafeAdjustMin1 :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMin1 f = go+  where+    go t =+      case t of+        Bin p l r     -> Bin p (go l) r++        Tip arr mx dx -> case mx of+                           Just x  -> Tip arr (Just $ f x) dx+                           Nothing -> Tip arr mx (go dx)++        Nil           -> Nil++++adjustMinWithKey0 :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMinWithKey0 f (RadixTree mx t) =+  case mx of+    Just x  -> RadixTree (Just $ f (Build Lin) x) t+    Nothing -> RadixTree mx $+                 case t of+                   Nil -> Nil+                   _   -> unsafeAdjustMinWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++adjustMinWithKey1 :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMinWithKey1 _ Nil = Nil+adjustMinWithKey1 f r   = unsafeAdjustMinWithKey1 f r++unsafeAdjustMinWithKey1 :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMinWithKey1 f = unsafeAdjustMinWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE unsafeAdjustMinWithKey_ #-}+unsafeAdjustMinWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMinWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> Bin p (go b l) r++        Tip arr mx dx -> case mx of+                           Just x  -> Tip arr (Just $ f b arr x) dx+                           Nothing -> Tip arr mx (go (Snoc b arr) dx)++        Nil           -> Nil++++adjustMax0 :: (a -> a) -> RadixTree a -> RadixTree a+adjustMax0 f t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just x  -> RadixTree (Just $ f x) t+             Nothing -> t0++    _   -> RadixTree mx (unsafeAdjustMax1 f t)++adjustMax1 :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMax1 _ Nil = Nil+adjustMax1 f r   = unsafeAdjustMax1 f r++unsafeAdjustMax1 :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMax1 f = go+  where+    go t =+      case t of+        Bin p l r     -> Bin p l (go r)++        Tip arr mx dx -> case dx of+                           Nil | Just x <- mx -> Tip arr (Just $ f x) dx+                           _                  -> Tip arr mx (go dx)++        Nil           -> Nil++++adjustMaxWithKey0 :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMaxWithKey0 f t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just x  -> RadixTree (Just $ f (Build Lin) x) t+             Nothing -> t0++    _   -> RadixTree mx $+             unsafeAdjustMaxWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++adjustMaxWithKey1 :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMaxWithKey1 _ Nil = Nil+adjustMaxWithKey1 f r   = unsafeAdjustMaxWithKey1 f r++unsafeAdjustMaxWithKey1 :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMaxWithKey1 f = unsafeAdjustMaxWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE unsafeAdjustMaxWithKey_ #-}+unsafeAdjustMaxWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMaxWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> Bin p l (go b r)++        Tip arr mx dx ->+          case dx of+            Nil | Just x <- mx -> Tip arr (Just $ f b arr x) dx+            _                  -> Tip arr mx (go (Snoc b arr) dx)++        Nil           -> Nil++++updateMin0 :: (a -> Maybe a) -> RadixTree a -> RadixTree a+updateMin0 f (RadixTree mx t) =+  case mx of+    Just x  -> RadixTree (f x) t+    Nothing -> RadixTree mx (updateMin1 f t)++updateMin1 :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMin1 _ Nil = Nil+updateMin1 f r   = unsafeUpdateMin1 f r++unsafeUpdateMin1 :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMin1 f = go+  where+    go t =+      case t of+        Bin p l r     -> rebinL p (go l) r++        Tip arr mx dx -> case mx of+                           Just x  -> retip arr (f x) dx+                           Nothing -> retip arr mx (go dx)++        Nil           -> Nil++++updateMinWithKey0 :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a+updateMinWithKey0 f (RadixTree mx t) =+  case mx of+    Just x  -> RadixTree (f (Build Lin) x) t+    Nothing -> RadixTree mx $+                 case t of+                   Nil -> Nil+                   _   -> unsafeUpdateMinWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++updateMinWithKey1 :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMinWithKey1 _ Nil = Nil+updateMinWithKey1 f r   = unsafeUpdateMinWithKey1 f r++unsafeUpdateMinWithKey1 :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMinWithKey1 f = unsafeUpdateMinWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE unsafeUpdateMinWithKey_ #-}+unsafeUpdateMinWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMinWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> rebinL p (go b l) r++        Tip arr mx dx -> case mx of+                           Just x  -> retip arr (f b arr x) dx+                           Nothing -> retip arr mx (go (Snoc b arr) dx)++        Nil           -> Nil++++updateMax0 :: (a -> Maybe a) -> RadixTree a -> RadixTree a+updateMax0 f t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just x  -> RadixTree (f x) t+             Nothing -> t0++    _   -> RadixTree mx (unsafeUpdateMax1 f t)++updateMax1 :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMax1 _ Nil = Nil+updateMax1 f r   = unsafeUpdateMax1 f r++unsafeUpdateMax1 :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMax1 f = go+  where+    go t =+      case t of+        Bin p l r     -> rebinR p l (go r)++        Tip arr mx dx -> case dx of+                           Nil | Just x <- mx -> retip arr (f x) dx+                           _                  -> retip arr mx (go dx)++        Nil           -> Nil++++updateMaxWithKey0 :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a+updateMaxWithKey0 f t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just x  -> RadixTree (f (Build Lin) x) t+             Nothing -> t0++    _   -> RadixTree mx $+             unsafeUpdateMaxWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++updateMaxWithKey1 :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMaxWithKey1 _ Nil = Nil+updateMaxWithKey1 f r   = unsafeUpdateMaxWithKey1 f r++unsafeUpdateMaxWithKey1 :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMaxWithKey1 f = unsafeUpdateMaxWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE unsafeUpdateMaxWithKey_ #-}+unsafeUpdateMaxWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMaxWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> rebinR p l (go b r)++        Tip arr mx dx -> case dx of+                           Nil | Just x <- mx -> retip arr (f b arr x) dx+                           _                  -> retip arr mx (go (Snoc b arr) dx)++        Nil           -> Nil++++-- | The leftmost value with its key and the rest of the tree.+data ViewL a = ViewL !Build a !(RadixTree a)+               deriving Show++minView0 :: RadixTree a -> Maybe (ViewL a)+minView0 (RadixTree mx t) =+  case mx of+    Just x  -> Just $! ViewL (Build Lin) x (RadixTree Nothing t)+    Nothing ->+      case t of+        Nil -> Nothing+        _   -> Just $! let !(# !b, !arr, x, !t' #) = unsafeMinView_ t+                       in ViewL (Build $ Snoc b arr) x (RadixTree mx t')+++-- | The leftmost value with its key and the rest of the tree.+data ViewL1 a = ViewL1 !Build1 a !(Radix1Tree a)+                deriving Show++minView1 :: Radix1Tree a -> Maybe (ViewL1 a)+minView1 Nil = Nothing+minView1 t   = Just $! unsafeMinView1 t++unsafeMinView1 :: Radix1Tree a -> ViewL1 a+unsafeMinView1 t =+  let !(# !b, !arr, x, !t' #) = unsafeMinView_ t+  in ViewL1 (Build1 $ b :/ arr) x t'++unsafeMinView_ :: Radix1Tree a -> (# Tsil ByteArray, ByteArray, a, Radix1Tree a #)+unsafeMinView_ = go Lin+  where+    go b t =+      case t of+        Bin p l r     ->+          let !(# !b', !brr, z, !l' #) = go b l+          in (# b', brr, z, rebinL p l' r #)++        Tip arr mx dx ->+          case mx of+            Just x  -> (# b, arr, x, retip arr Nothing dx #)+            Nothing ->+              let !(# !b', !brr, z, !dy #) = go (Snoc b arr) dx+              in (# b', brr, z, retip arr mx dy #)++        Nil           -> throw $ MalformedTree moduleLoc1 "minView"++++-- | The rightmost value with its key and the rest of the tree.+data ViewR a = ViewR !(RadixTree a) !Build a+               deriving Show++maxView0 :: RadixTree a -> Maybe (ViewR a)+maxView0 (RadixTree mx t) =+  case t of+    Nil -> ViewR (RadixTree Nothing t) (Build Lin) `fmap'` mx+    _   -> Just $! let !(# !t', !b, !arr, x #) = unsafeMaxView_ t+                   in ViewR (RadixTree mx t') (Build $ Snoc b arr) x+++-- | The rightmost value with its key and the rest of the tree.+data ViewR1 a = ViewR1 !(Radix1Tree a) !Build1 a+                deriving Show++maxView1 :: Radix1Tree a -> Maybe (ViewR1 a)+maxView1 Nil = Nothing+maxView1 t   = Just $! unsafeMaxView1 t++unsafeMaxView1 :: Radix1Tree a -> ViewR1 a+unsafeMaxView1 t =+  let !(# !t', !b, !arr, x #) = unsafeMaxView_ t+  in ViewR1 t' (Build1 $ b :/ arr) x++unsafeMaxView_ :: Radix1Tree a -> (# Radix1Tree a, Tsil ByteArray, ByteArray, a #)+unsafeMaxView_ = go Lin+  where+    go b t =+      case t of+        Bin p l r     ->+          let !(# !r', !b', !brr, z #) = go b r+          in (# rebinR p l r', b', brr, z #)++        Tip arr mx dx ->+          case dx of+            Nil | Just x <- mx -> (# retip arr Nothing dx, b, arr, x #)+            _                  ->+              let !(# !dy, !b', !brr, z #) = go (Snoc b arr) dx+              in (# retip arr mx dy, b', brr, z #)++        Nil           -> throw $ MalformedTree moduleLoc1 "maxView"
+ src/Data/RadixNTree/Word8/Lazy/Debug.hs view
@@ -0,0 +1,109 @@+module Data.RadixNTree.Word8.Lazy.Debug+  ( showsTree0+  , showsTree1++  , Validity (..)+  , Reason (..)+  , validate0+  , validate1+  ) where++import           Data.ByteArray.NonEmpty+import           Data.RadixNTree.Word8.Debug+import           Data.RadixNTree.Word8.Key+import           Data.RadixNTree.Word8.Lazy+import           Numeric.Long+import           Radix.Word8.Debug++import           Data.List.NonEmpty (NonEmpty (..))+import           Data.Primitive.ByteArray++++showsTree0 :: (a -> ShowS) -> RadixTree a -> ShowS+showsTree0 f (RadixTree mx t) =+  showString "RadixTree" . case mx of+                             Just x  -> showString " => " . f x+                             Nothing -> id++                         . showChar '\n'++                         . showsTree_ 2 f t++showsTree1 :: (a -> ShowS) -> Radix1Tree a -> ShowS+showsTree1 f = showsTree_ 0 f++showsTree_ :: Int -> (a -> ShowS) -> Radix1Tree a -> ShowS+showsTree_ n0 f = go n0+  where+    go i t =+      mappend (replicate i ' ') .+        case t of+          Bin p l r   ->+            showString "Bin " . showPrefix p . showChar '\n'+                              . go (i + 2) l . showChar '\n'+                              . go (i + 2) r++          Tip arr mx dx ->+            showString "Tip " . if sizeofByteArray arr <= 0+                                  then id+                                  else let w0 :| ws = toNonEmpty arr+                                       in showLongBin w0+                                            . showString " (" . showLongHex w0 . showChar ')'+                                            . foldr (\x s -> showChar ' ' . showLongHex x . s) id ws++                                 . case mx of+                                     Just x  -> showString " => " . f x+                                     Nothing -> id++                                 . showChar '\n'++                                 . go (i + 2) dx++          Nil           -> showString "Nil"++++validate0 :: RadixTree a -> Validity+validate0 (RadixTree _ t) = validate1 t++validate1 :: Radix1Tree a -> Validity+validate1 = go Lin+  where+    go b t =+      case t of+        Bin p l r+          | p == 0                 -> Invalid (Build b) ZeroPrefix+          | otherwise              ->+              case goBin L b p l of+                Valid -> goBin R b p r+                err   -> err++        Tip arr mx dx+          | sizeofByteArray arr <= 0       -> Invalid (Build b) EmptyByteArray+          | Nothing <- mx, Tip _ _ _ <- dx -> Invalid (Build b) UncompressedTip+          | Nothing <- mx, Nil       <- dx -> Invalid (Build b) UncompressedTip+          | otherwise                      -> go (Snoc b arr) dx++        Nil -> Valid++    goBin s b q x =+      case x of+        Bin p l r+          | p == 0                 -> Invalid (Build b) ZeroPrefix+          | not $ validBelow q s p -> Invalid (Build b) $ PrefixBelow q p+          | otherwise              ->+              case goBin L b p l of+                Valid -> goBin R b p r+                err   -> err++        Tip arr mx dx+          | sizeofByteArray arr <= 0                    -> Invalid (Build b) EmptyByteArray+          | not $ validBelow q s (indexByteArray arr 0) ->+              Invalid (Build b) $ KeyBelow q (indexByteArray arr 0)++          | Nothing <- mx, Tip _ _ _ <- dx     -> Invalid (Build b) UncompressedTip+          | Nothing <- mx, Nil       <- dx     -> Invalid (Build b) UncompressedTip+          | otherwise                          -> go (Snoc b arr) dx++        Nil -> Invalid (Build b) $ MalformedBin q
+ src/Data/RadixNTree/Word8/Lazy/TH.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE TemplateHaskellQuotes #-}++module Data.RadixNTree.Word8.Lazy.TH+  ( RadixTree+  , sequenceCode0++  , Radix1Tree+  , sequenceCode1+  ) where++import           Data.RadixNTree.Word8.Lazy++import           Language.Haskell.TH.Syntax++++sequenceCode0 :: Quote m => RadixTree (Code m a) -> Code m (RadixTree a)+sequenceCode0 (RadixTree mx t) =+  [|| RadixTree $$(sequenceMaybe mx) $$(sequenceCode1 t) ||]++sequenceCode1 :: Quote m => Radix1Tree (Code m a) -> Code m (Radix1Tree a)+sequenceCode1 t =+  case t of+    Bin p l r     ->+      [|| Bin+            p+            $$(sequenceCode1 l)+            $$(sequenceCode1 r)+       ||]++    Tip arr mx dx -> [|| Tip arr $$(sequenceMaybe mx) $$(sequenceCode1 dx) ||]++    Nil           -> [|| Nil ||]++++sequenceMaybe :: Quote m => Maybe (Code m a) -> Code m (Maybe a)+sequenceMaybe mx =+  case mx of+    Just x  -> [|| Just $$(x) ||]+    Nothing -> [|| Nothing ||]
+ src/Data/RadixNTree/Word8/Strict.hs view
@@ -0,0 +1,5643 @@+{-# LANGUAGE BangPatterns+           , GADTs+           , RankNTypes+           , ScopedTypeVariables+           , UnboxedTuples #-}++module Data.RadixNTree.Word8.Strict+  ( StrictRadixTree+  , RadixTree (..)++  , StrictRadix1Tree+  , Radix1Tree (..)++  , empty0+  , empty1++  , singleton0+  , singleton1++  , map0+  , map0'+  , mapWithKey0+  , mapWithKey0'++  , map1+  , map1'+  , mapWithKey1+  , mapWithKey1'++  , foldl0+  , foldl0'+  , foldlWithKey0+  , foldlWithKey0'++  , Data.RadixNTree.Word8.Strict.foldl1+  , foldl1'+  , foldlWithKey1+  , foldlWithKey1'++  , foldr0+  , foldr0'+  , foldrWithKey0+  , foldrWithKey0'++  , Data.RadixNTree.Word8.Strict.foldr1+  , foldr1'+  , foldrWithKey1+  , foldrWithKey1'++  , foldMap0+  , foldMapWithKey0++  , foldMap1+  , foldMapWithKey1++  , traverse0+  , traverseWithKey0++  , traverse1+  , traverseWithKey1++  , null0+  , null1++  , size0+  , size1++  , lookup0+  , find0+  , member0+  , subtree0+  , prefix0++  , lookup1+  , find1+  , member1+  , subtree1+  , prefix1++  , Point (..)+  , Cursor (..)+  , stop++  , Location (..)+  , locate++  , cursor0+  , move0++  , cursor1+  , move1++  , lookupL0+  , lookupL1++  , lookupR0+  , lookupR1++  , adjustL0+  , adjustL0'+  , adjustLWithKey0+  , adjustLWithKey0'++  , adjustL1+  , adjustL1'+  , adjustLWithKey1+  , adjustLWithKey1'++  , adjustR0+  , adjustR0'+    , adjustRWithKey0+  , adjustRWithKey0'++  , adjustR1+  , adjustR1'+  , adjustRWithKey1+  , adjustRWithKey1'++  , updateL0+  , updateLWithKey0++  , updateL1+  , updateLWithKey1++  , updateR0+  , updateRWithKey0++  , updateR1+  , updateRWithKey1++  , takeL0+  , takeL1++  , takeR0+  , takeR1++  , union0+  , union1++  , unionL0+  , unionL1++  , unionWith0'+  , unionWith1'++  , unionWithKey0'+  , unionWithKey1'++  , difference0+  , difference1++  , differenceWith0+  , differenceWith1++  , differenceWithKey0+  , differenceWithKey1++  , compare0+  , Data.RadixNTree.Word8.Strict.compare1++  , disjoint0+  , disjoint1++  , intersection0+  , intersection1++  , intersectionL0+  , intersectionL1++  , intersectionWith0'+  , intersectionWith1'++  , intersectionWithKey0'+  , intersectionWithKey1'++  , merge0+  , merge1++  , insert0+  , insert1++  , insertWith0+  , insertWith0'++  , insertWith1+  , insertWith1'++  , adjust0+  , adjust0'++  , adjust1+  , adjust1'++  , delete0+  , delete1++  , prune0+  , prune1++  , update0+  , update1++  , alter0+  , alter1++  , shape0+  , shape1++  , Split (..)+  , Split1 (..)+  , splitL0+  , splitL1++  , SplitLookup (..)+  , SplitLookup1 (..)+  , splitLookup0+  , splitLookup1++  , filter0+  , filterWithKey0++  , filter1+  , filterWithKey1++  , mapMaybe0+  , mapMaybeWithKey0++  , mapMaybe1+  , mapMaybeWithKey1++  , partition0+  , partitionWithKey0++  , partition1+  , partitionWithKey1++  , mapEither0+  , mapEitherWithKey0++  , mapEither1+  , mapEitherWithKey1++  , lookupMin0+  , lookupMin1+  , unsafeLookupMin1++  , lookupMinWithKey0+  , lookupMinWithKey1+  , unsafeLookupMinWithKey1++  , lookupMax0+  , lookupMax1+  , unsafeLookupMax1++  , lookupMaxWithKey0+  , lookupMaxWithKey1+  , unsafeLookupMaxWithKey1++  , deleteMin0+  , deleteMin1+  , unsafeDeleteMin1++  , deleteMax0+  , deleteMax1+  , unsafeDeleteMax1++  , adjustMin0+  , adjustMin1+  , unsafeAdjustMin1++  , adjustMin0'+  , adjustMin1'+  , unsafeAdjustMin1'++  , adjustMinWithKey0+  , adjustMinWithKey1+  , unsafeAdjustMinWithKey1++  , adjustMinWithKey0'+  , adjustMinWithKey1'+  , unsafeAdjustMinWithKey1'++  , adjustMax0+  , adjustMax1+  , unsafeAdjustMax1++  , adjustMax0'+  , adjustMax1'+  , unsafeAdjustMax1'++  , adjustMaxWithKey0+  , adjustMaxWithKey1+  , unsafeAdjustMaxWithKey1++  , adjustMaxWithKey0'+  , adjustMaxWithKey1'+  , unsafeAdjustMaxWithKey1'++  , updateMin0+  , updateMin1+  , unsafeUpdateMin1++  , updateMinWithKey0+  , updateMinWithKey1+  , unsafeUpdateMinWithKey1++  , updateMax0+  , updateMax1+  , unsafeUpdateMax1++  , updateMaxWithKey0+  , updateMaxWithKey1+  , unsafeUpdateMaxWithKey1++  , ViewL (..)+  , ViewL1 (..)+  , minView0+  , minView1+  , unsafeMinView1++  , ViewR (..)+  , ViewR1 (..)+  , maxView0+  , maxView1+  , unsafeMaxView1+  ) where++import           Data.ByteArray.NonEmpty+import           Data.RadixNTree.Word8.Common+import           Data.RadixNTree.Word8.Key+import           Radix.Common+import           Radix.Exception+import           Radix.Word8.Common+import           Radix.Word8.Foundation++import           Control.Applicative+import           Control.Exception (throw)+import           Control.DeepSeq+import           Data.Bits+import           Data.Foldable+import           Data.Functor.Classes+import           Data.Primitive.ByteArray+import           Data.Word+import           Text.Show++++-- | Convenience type synonym.+type StrictRadixTree = RadixTree++-- | Spine-strict radix tree with byte sequences as keys.+data RadixTree a = RadixTree+                     {-# UNPACK #-} !(Maybe a) -- ^ Value at the empty byte sequence key.+                     !(Radix1Tree a)++instance Show a => Show (RadixTree a) where+  showsPrec = liftShowsPrec showsPrec showList++instance Show1 RadixTree where+  liftShowsPrec showsPrec_ showList_ d t =+    showParen (d > 10) $+      showListWith (liftShowsPrec showsPrec_ showList_ 0) $+        foldrWithKey0 (\k a -> (:) (k, a)) [] t++instance Eq a => Eq (RadixTree a) where+  (==) = liftEq (==)++instance Eq1 RadixTree where+  liftEq eq (RadixTree mx l) (RadixTree my r) = liftEq eq mx my && liftEq eq l r++-- | Uses 'Data.RadixTree.Word8.Strict.map'.+instance Functor RadixTree where+  fmap = map0++instance Foldable RadixTree where+  foldl = foldl0+  foldr = foldr0+  foldMap = foldMap0++  foldl' = foldl0'+  foldr' = foldr0'++  null = null0++  length = size0++instance Traversable RadixTree where+  traverse = traverse0+++instance NFData a => NFData (RadixTree a) where+  rnf = liftRnf rnf++instance NFData1 RadixTree where+  liftRnf nf (RadixTree mx t) = liftRnf nf mx `seq` liftRnf nf t++++-- | Convenience type synonym.+type StrictRadix1Tree = Radix1Tree++-- | Spine-strict radix tree with non-empty byte sequences as keys.+data Radix1Tree a = Bin+                      {-# UNPACK #-} !Prefix+                      !(Radix1Tree a)        -- ^ Masked bit is @0@. Invariant: not 'Nil'.+                      !(Radix1Tree a)        -- ^ Masked bit is @1@. Invariant: not 'Nil'.++                  | Tip+                      {-# UNPACK #-} !ByteArray -- ^ Invariant: non-empty.+                      {-# UNPACK #-} !(Maybe a) -- ^ Invariant: can only be 'Nothing' when+                                                --   the tree below is 'Bin'.+                      !(Radix1Tree a)++                  | Nil++instance Show a => Show (Radix1Tree a) where+  showsPrec = liftShowsPrec showsPrec showList++instance Show1 Radix1Tree where+  liftShowsPrec showsPrec_ showList_ d t =+    showParen (d > 10) $+      showListWith (liftShowsPrec showsPrec_ showList_ 0) $+        foldrWithKey1 (\k a -> (:) (k, a)) [] t++instance Eq a => Eq (Radix1Tree a) where+  (==) = liftEq (==)++instance Eq1 Radix1Tree where+  liftEq eq = go+    where+      go l r =+        case l of+          Bin p xl xr ->+            case r of+              Bin q yl yr -> p == q && go xl yl && go xr yr+              _           -> False++          Tip arr mx dx ->+            case r of+              Tip brr my dy -> arr == brr && liftEq eq mx my && go dx dy+              _             -> False++          Nil ->+            case r of+              Nil -> True+              _   -> False++-- | Uses 'Data.Radix1Tree.Word8.Strict.map'.+instance Functor Radix1Tree where+  fmap = map1++instance Foldable Radix1Tree where+  foldl = Data.RadixNTree.Word8.Strict.foldl1+  foldr = Data.RadixNTree.Word8.Strict.foldr1+  foldMap = foldMap1++  foldl' = foldl1'+  foldr' = foldr1'++  null = null1++  length = size1++instance Traversable Radix1Tree where+  traverse = traverse1+++instance NFData a => NFData (Radix1Tree a) where+  rnf = liftRnf rnf++instance NFData1 Radix1Tree where+  liftRnf nf = go+    where+      go t =+        case t of+          Bin _ l r   -> go l `seq` go r+          Tip _ mx dx -> liftRnf nf mx `seq` go dx+          Nil         -> ()++++{-# INLINE join #-}+-- | Knowing that the prefices of two trees disagree, construct a 'Bin'.+join :: Prefix -> Radix1Tree a -> Prefix -> Radix1Tree a -> Radix1Tree a+join p0 t0 p1 t1 =+  let m = branchingBit p0 p1++      p = mask p0 m .|. m++  in if zeroBit p0 m+       then Bin p t0 t1+       else Bin p t1 t0++{-# INLINE safeJoin #-}+safeJoin :: Prefix -> Radix1Tree a -> Prefix -> Radix1Tree a -> Radix1Tree a+safeJoin _ Nil _  t1    = t1+safeJoin _ t0    _  Nil = t0+safeJoin p0 t0   p1 t1  = join p0 t0 p1 t1++{-# INLINE retip #-}+-- | Based on the altered entry and/or downward state, fuse or remove the 'Tip' as needed.+retip :: ByteArray -> Maybe a -> Radix1Tree a -> Radix1Tree a+retip arr mx dx =+  case mx of+    Just _  -> Tip arr mx dx+    Nothing ->+     case dx of+       Bin _ _ _     -> Tip arr mx dx+       Tip brr my dy -> Tip (appendByteArray arr brr) my dy+       Nil           -> Nil++{-# INLINE dropTrim #-}+dropTrim :: Int -> ByteArray -> Maybe a -> Radix1Tree a -> Radix1Tree a+dropTrim n arr mx dx =+  case mx of+    Just _  -> Tip (dropByteArray n arr) mx dx+    Nothing ->+     case dx of+       Bin _ _ _     -> Tip (dropByteArray n arr) mx dx+       Tip brr my dy -> Tip (dropAppendByteArray n arr brr) my dy+       Nil           -> Nil+++{-# INLINE rebin #-}+rebin :: Prefix -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+rebin p l r =+  case l of+    Nil -> r+    _     -> case r of+               Nil -> l+               _     -> Bin p l r++{-# INLINE rebinL #-}+rebinL :: Prefix -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+rebinL p l r =+  case l of+    Nil -> r+    _   -> Bin p l r++{-# INLINE rebinR #-}+rebinR :: Prefix -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+rebinR p l r =+  case r of+    Nil -> l+    _   -> Bin p l r++++empty0 :: RadixTree a+empty0 = RadixTree Nothing Nil++empty1 :: Radix1Tree a+empty1 = Nil++++{-# INLINE singleton0 #-}+singleton0 :: Feed -> a -> RadixTree a+singleton0 (Feed feed) = \a ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree Nothing $ singleton1 (Feed1 w (\g -> g step z)) a+      Done     -> RadixTree (Just a) Nil++{-# INLINE singleton1 #-}+singleton1 :: Feed1 -> a -> Radix1Tree a+singleton1 (Feed1 w feed) = \a -> feed $ \step s -> singleton_ step w s a++{-# INLINE singleton_ #-}+-- | \(\mathcal{O}(1)\). Single element radix tree.+singleton_ :: (b -> Step Word8 b) -> Word8 -> b -> a -> Radix1Tree a+singleton_ step w s = \a -> Tip (fromStep step w s) (Just a) Nil++++null0 :: RadixTree a -> Bool+null0 (RadixTree Nothing t) = null1 t+null0 _                     = False++null1 :: Radix1Tree a -> Bool+null1 Nil = True+null1 _   = False++++size0 :: RadixTree a -> Int+size0 (RadixTree mx t) =+  let !n = size1 t+  in case mx of+       Just _  -> n + 1+       Nothing -> n++size1 :: Radix1Tree a -> Int+size1 = go 0+  where+    go z t =+      case t of+        Bin _ l r   -> let !n = go z l+                       in go n r++        Tip _ mx dx -> case mx of+                         Nothing -> go z dx+                         Just _  -> let !n = go z dx+                                    in n + 1+        Nil         -> z++++{-# INLINE fmap' #-}+fmap' :: (a -> b) -> Maybe a -> Maybe b+fmap' f (Just x) = Just $! f x+fmap' _ Nothing  = Nothing++++map0 :: (a -> b) -> RadixTree a -> RadixTree b+map0 f (RadixTree mx t) = RadixTree (fmap f mx) $ map1 f t++map1 :: (a -> b) -> Radix1Tree a -> Radix1Tree b+map1 f = go+  where+    go t =+      case t of+        Bin p l r     -> Bin p (go l) (go r)+        Tip arr mx dx -> Tip arr (fmap f mx) (go dx)+        Nil           -> Nil++++map0' :: (a -> b) -> RadixTree a -> RadixTree b+map0' f (RadixTree mx t) = RadixTree (fmap' f mx) $ map1 f t++map1' :: (a -> b) -> Radix1Tree a -> Radix1Tree b+map1' f = go+  where+    go t =+      case t of+        Bin p l r     -> Bin p (go l) (go r)+        Tip arr mx dx -> Tip arr (fmap' f mx) (go dx)+        Nil           -> Nil++++mapWithKey0 :: (Build -> a -> b) -> RadixTree a -> RadixTree b+mapWithKey0 f (RadixTree mx t) =+  RadixTree (f (Build Lin) <$> mx) $+    mapWithKey_ (\b arr -> f (Build $ Snoc b arr)) Lin t++mapWithKey1 :: (Build1 -> a -> b) -> Radix1Tree a -> Radix1Tree b+mapWithKey1 f = mapWithKey_ (\b arr -> f (Build1 $ b :/ arr)) Lin++{-# INLINE mapWithKey_ #-}+mapWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> b) -> Tsil ByteArray+  -> Radix1Tree a -> Radix1Tree b+mapWithKey_ f = go+  where+    go b t =+      case t of+        Bin p l r     -> Bin p (go b l) (go b r)+        Tip arr mx dx -> Tip arr (f b arr <$> mx) (go (Snoc b arr) dx)+        Nil           -> Nil++++mapWithKey0' :: (Build -> a -> b) -> RadixTree a -> RadixTree b+mapWithKey0' f (RadixTree mx t) =+  RadixTree (f (Build Lin) `fmap'` mx) $+    mapWithKey'_ (\b arr -> f (Build $ Snoc b arr)) Lin t++mapWithKey1' :: (Build1 -> a -> b) -> Radix1Tree a -> Radix1Tree b+mapWithKey1' f = mapWithKey'_ (\b arr -> f (Build1 $ b :/ arr)) Lin++{-# INLINE mapWithKey'_ #-}+mapWithKey'_+  :: (Tsil ByteArray -> ByteArray -> a -> b) -> Tsil ByteArray+  -> Radix1Tree a -> Radix1Tree b+mapWithKey'_ f = go+  where+    go b t =+      case t of+        Bin p l r     -> Bin p (go b l) (go b r)+        Tip arr mx dx -> Tip arr (f b arr `fmap'` mx) (go (Snoc b arr) dx)+        Nil           -> Nil++++foldl0 :: (b -> a -> b) -> b -> RadixTree a -> b+foldl0 f z (RadixTree mx t) =+  let z' = case mx of+             Just x  -> f z x+             Nothing -> z++  in Data.RadixNTree.Word8.Strict.foldl1 f z' t++foldl1 :: (b -> a -> b) -> b -> Radix1Tree a -> b+foldl1 f = go+  where+    go z t =+      case t of+        Bin _ l r   -> go (go z l) r++        Tip _ mx dx -> let z' = case mx of+                                  Just x  -> f z x+                                  Nothing -> z++                       in go z' dx++        Nil         -> z++++foldl0' :: (b -> a -> b) -> b -> RadixTree a -> b+foldl0' f z (RadixTree mx t) =+  let !z' = case mx of+              Just x  -> f z x+              Nothing -> z++  in Data.RadixNTree.Word8.Strict.foldl1' f z' t++foldl1' :: (b -> a -> b) -> b -> Radix1Tree a -> b+foldl1' f = go+  where+    go !z t =+      case t of+        Bin _ l r   -> let !z' = go z l+                       in go z' r++        Tip _ mx dx -> let !z' = case mx of+                                   Just x  -> f z x+                                   Nothing -> z++                       in go z' dx++        Nil         -> z++++foldlWithKey0 :: (b -> Build -> a -> b) -> b -> RadixTree a -> b+foldlWithKey0 f z (RadixTree mx t) =+  let z' = case mx of+             Just x  -> f z (Build Lin) x+             Nothing -> z++  in foldlWithKey_ (\z'' b arr -> f z'' (Build $ Snoc b arr)) z' t++foldlWithKey1 :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey1 f = foldlWithKey_ (\z b arr -> f z (Build1 $ b :/ arr))++{-# INLINE foldlWithKey_ #-}+foldlWithKey_ :: (b -> Tsil ByteArray -> ByteArray -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey_ f = go Lin+  where+    go b z t =+      case t of+        Bin _ l r     -> go b (go b z l) r++        Tip arr mx dx ->+          case mx of+            Nothing -> go (Snoc b arr) z dx+            Just a  -> go (Snoc b arr) (f z b arr a) dx++        Nil           -> z++++foldlWithKey0' :: (b -> Build -> a -> b) -> b -> RadixTree a -> b+foldlWithKey0' f z (RadixTree mx t) =+  let !z' = case mx of+              Just x  -> f z (Build Lin) x+              Nothing -> z++  in foldlWithKey'_ (\z'' b arr -> f z'' (Build $ Snoc b arr)) z' t++foldlWithKey1' :: (b -> Build1 -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey1' f = foldlWithKey'_ (\z b arr -> f z (Build1 $ b :/ arr))++{-# INLINE foldlWithKey'_ #-}+foldlWithKey'_ :: (b -> Tsil ByteArray -> ByteArray -> a -> b) -> b -> Radix1Tree a -> b+foldlWithKey'_ f = go Lin+  where+    go b !z t =+      case t of+        Bin _ l r     -> let !z' = go b z l+                         in go b z' r++        Tip arr mx dx ->+          case mx of+            Nothing -> go (Snoc b arr) z dx+            Just a  -> let !z' = f z b arr a+                       in go (Snoc b arr) z' dx++        Nil           -> z++++foldr0 :: (a -> b -> b) -> b -> RadixTree a -> b+foldr0 f z (RadixTree mx t) =+  let z' = Data.RadixNTree.Word8.Strict.foldr1 f z t+  in case mx of+       Just x  -> f x z'+       Nothing -> z'++foldr1 :: (a -> b -> b) -> b -> Radix1Tree a -> b+foldr1 f = go+  where+    go z t =+      case t of+        Bin _ l r   -> go (go z r) l++        Tip _ mx dx -> let z' = go z dx+                       in case mx of+                            Just x  -> f x z'+                            Nothing -> z'++        Nil         -> z++++foldr0' :: (a -> b -> b) -> b -> RadixTree a -> b+foldr0' f z (RadixTree mx t) =+  let !z' = Data.RadixNTree.Word8.Strict.foldr1' f z t+  in case mx of+       Just x  -> f x z'+       Nothing -> z'++foldr1' :: (a -> b -> b) -> b -> Radix1Tree a -> b+foldr1' f = go+  where+    go !z t =+      case t of+        Bin _ l r   -> let !z' = go z r+                       in go z' l++        Tip _ mx dx -> let !z' = go z dx+                       in case mx of+                            Just x  -> f x z'+                            Nothing -> z'++        Nil         -> z++++foldrWithKey0 :: (Build -> a -> b -> b) -> b -> RadixTree a -> b+foldrWithKey0 f z (RadixTree mx t) =+  let z' = foldrWithKey_ (\b arr -> f (Build $ Snoc b arr)) z t+  in case mx of+       Just x  -> f (Build Lin) x z'+       Nothing -> z'++foldrWithKey1 :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey1 f = foldrWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE foldrWithKey_ #-}+foldrWithKey_ :: (Tsil ByteArray -> ByteArray -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey_ f = go Lin+  where+    go b z t =+      case t of+        Bin _ l r     -> go b (go b z r) l++        Tip arr mx dx -> let z' = go (Snoc b arr) z dx+                         in case mx of+                              Just x  -> f b arr x z'+                              Nothing -> z'++        Nil           -> z++++foldrWithKey0' :: (Build -> a -> b -> b) -> b -> RadixTree a -> b+foldrWithKey0' f z (RadixTree mx t) =+  let !z' = foldrWithKey'_ (\b arr -> f (Build $ Snoc b arr)) z t+  in case mx of+       Just x  -> f (Build Lin) x z'+       Nothing -> z'++foldrWithKey1' :: (Build1 -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey1' f = foldrWithKey'_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE foldrWithKey'_ #-}+foldrWithKey'_ :: (Tsil ByteArray -> ByteArray -> a -> b -> b) -> b -> Radix1Tree a -> b+foldrWithKey'_ f = go Lin+  where+    go b !z t =+      case t of+        Bin _ l r     -> let !z' = go b z r+                         in go b z' l++        Tip arr mx dx -> let !z' = go (Snoc b arr) z dx+                         in case mx of+                              Just x  -> f b arr x z'+                              Nothing -> z'++        Nil           -> z++++foldMap0 :: Monoid m => (a -> m) -> RadixTree a -> m+foldMap0 f (RadixTree mx t) =+  let m = foldMap1 f t+  in case mx of+       Just x  -> f x <> m+       Nothing -> m++foldMap1 :: Monoid m => (a -> m) -> Radix1Tree a -> m+foldMap1 f = go+  where+    go t =+      case t of+        Bin _ l r   -> go l <> go r++        Tip _ mx dx -> let m = go dx+                       in case mx of+                            Nothing -> m+                            Just a  -> f a <> m++        Nil         -> mempty++++foldMapWithKey0 :: Monoid m => (Build -> a -> m) -> RadixTree a -> m+foldMapWithKey0 f (RadixTree mx t) =+  let m = foldMapWithKey_ (\b arr -> f (Build $ Snoc b arr)) t+  in case mx of+       Just x  -> f (Build Lin) x <> m+       Nothing -> m++foldMapWithKey1 :: Monoid m => (Build1 -> a -> m) -> Radix1Tree a -> m+foldMapWithKey1 f = foldMapWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE foldMapWithKey_ #-}+foldMapWithKey_+  :: Monoid m => (Tsil ByteArray -> ByteArray -> a -> m) -> Radix1Tree a -> m+foldMapWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin _ l r     -> go b l <> go b r++        Tip arr mx dx ->+          let m = go (Snoc b arr) dx+          in case mx of+               Nothing -> m+               Just a  -> f b arr a <> m++        Nil           -> mempty++++traverse0 :: Applicative f => (a -> f b) -> RadixTree a -> f (RadixTree b)+traverse0 f (RadixTree mx t) =+  let dy = traverse1 f t+  in case mx of+       Just x  -> liftA2 RadixTree (Just <$> f x) dy+       Nothing -> RadixTree Nothing <$> dy++traverse1 :: Applicative f => (a -> f b) -> Radix1Tree a -> f (Radix1Tree b)+traverse1 f = go+  where+    go t =+      case t of+        Bin p l r     -> liftA2 (Bin p) (go l) (go r)++        Tip arr mx dx ->+          case mx of+            Nothing -> Tip arr Nothing <$> go dx+            Just x  -> liftA2 (Tip arr . Just) (f x) (go dx)++        Nil           -> pure Nil++++traverseWithKey0 :: Applicative f => (Build -> a -> f b) -> RadixTree a -> f (RadixTree b)+traverseWithKey0 f (RadixTree mx t) =+  let dy = traverseWithKey_ (\b arr -> f (Build $ Snoc b arr)) t+  in case mx of+       Just x  -> liftA2 RadixTree (Just <$> f (Build Lin) x) dy+       Nothing -> RadixTree Nothing <$> dy++traverseWithKey1+  :: Applicative f => (Build1 -> a -> f b) -> Radix1Tree a -> f (Radix1Tree b)+traverseWithKey1 f = traverseWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE traverseWithKey_ #-}+traverseWithKey_+  :: Applicative f+  => (Tsil ByteArray -> ByteArray -> a -> f b) -> Radix1Tree a -> f (Radix1Tree b)+traverseWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> liftA2 (Bin p) (go b l) (go b r)++        Tip arr mx dx ->+          let dy = go (Snoc b arr) dx+          in case mx of+               Nothing -> Tip arr Nothing <$> dy+               Just a  -> liftA2 (Tip arr . Just) (f b arr a) dy++        Nil           -> pure Nil++++{-# INLINE lookup0 #-}+lookup0 :: Feed -> RadixTree a -> Maybe a+lookup0 (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> lookup_ step w z t+      Done     -> mx++{-# INLINE lookup1 #-}+lookup1 :: Feed1 -> Radix1Tree a -> Maybe a+lookup1 (Feed1 w feed) = feed $ \step -> lookup_ step w++{-# INLINE lookup_ #-}+lookup_ :: (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Maybe a+lookup_ step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          go w s $ if w < p+                     then l+                     else r++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  let n' = n + 1+                  in if n' >= sizeofByteArray arr+                       then case step z of+                              More u z' -> go u z' dx+                              Done      -> mx++                       else case step z of+                              More u z' -> goarr u z' n'+                              Done      -> Nothing++              | otherwise = Nothing++        Nil -> Nothing++++{-# INLINE find0 #-}+find0 :: a -> Feed -> RadixTree a -> a+find0 d (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> find_ d step w z t+      Done     -> case mx of+                    Just x  -> x+                    Nothing -> d++{-# INLINE find1 #-}+find1 :: a -> Feed1 -> Radix1Tree a -> a+find1 d (Feed1 w feed) = feed $ \step -> find_ d step w++{-# INLINE find_ #-}+find_ :: a -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> a+find_ d step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          go w s $ if w < p+                     then l+                     else r++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  let n' = n + 1+                  in if n' >= sizeofByteArray arr+                       then case step z of+                              More u z' -> go u z' dx+                              Done      -> case mx of+                                             Just x  -> x+                                             Nothing -> d++                       else case step z of+                              More u z' -> goarr u z' n'+                              Done      -> d++              | otherwise = d++        Nil -> d++++{-# INLINE member0 #-}+member0 :: Feed -> RadixTree a -> Bool+member0 (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> member_ step w z t+      Done     -> case mx of+                    Just _  -> True+                    Nothing -> False++{-# INLINE member1 #-}+member1 :: Feed1 -> Radix1Tree a -> Bool+member1 (Feed1 w feed) = feed $ \step -> member_ step w++{-# INLINE member_ #-}+member_ :: (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Bool+member_ step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          go w s $ if w < p+                     then l+                     else r++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  let n' = n + 1+                  in if n' >= sizeofByteArray arr+                       then case step z of+                              More u z' -> go u z' dx+                              Done      -> case mx of+                                             Just _  -> True+                                             Nothing -> False++                       else case step z of+                              More u z' -> goarr u z' n'+                              Done      -> False++              | otherwise = False++        Nil -> False++++{-# INLINE subtree0 #-}+subtree0 :: Feed -> RadixTree a -> RadixTree a+subtree0 (Feed feed) = \t0@(RadixTree _ t) ->+  feed $ \step s ->+    case step s of+      More w z -> subtree_ step w z t+      Done     -> t0++{-# INLINE subtree1 #-}+subtree1 :: Feed1 -> Radix1Tree a -> RadixTree a+subtree1 (Feed1 w feed) = feed $ \step -> subtree_ step w++{-# INLINE subtree_ #-}+subtree_ :: (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> RadixTree a+subtree_ step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          go w s $ if w < p+                     then l+                     else r++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> go u z' dx+                           Done      -> RadixTree mx dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> let rest = dropTrim (n + 1) arr mx dx+                                        in rest `seq` RadixTree Nothing rest++              | otherwise = RadixTree Nothing Nil++        Nil -> RadixTree Nothing Nil++++{-# INLINE prefix0 #-}+prefix0 :: Feed -> RadixTree a -> RadixTree a+prefix0 (Feed feed) = \t ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree Nothing $ prefix_ step w z t+      Done     -> t++{-# INLINE prefix1 #-}+prefix1 :: Feed1 -> RadixTree a -> Radix1Tree a+prefix1 (Feed1 w feed) =+  feed $ \step -> prefix_ step w++{-# INLINE prefix_ #-}+prefix_ :: (x -> Step Word8 x) -> Word8 -> x -> RadixTree a -> Radix1Tree a+prefix_ step = \w z (RadixTree mx t) ->+  case mx of+    Nothing ->+      case t of+        Bin _ _ _     -> Tip (fromStep step w z) Nothing t+        Tip arr my dy -> Tip (fromStepAppend step w z arr) my dy+        Nil           -> Nil++    Just _  -> Tip (fromStep step w z) mx t++++-- | Current position in the tree.+data Point = -- | Above a node.+             Seam++             -- | In the middle of a 'Tip'.+           | Plane+               {-# UNPACK #-} !Int       -- ^ Always greater than @0@ and smaller than+                                         --   the length of the 'ByteArray'.+               {-# UNPACK #-} !ByteArray++-- | A particular point in the tree.+data Cursor a = -- | This is effectively a 'Tip' where the 'ByteArray' is optional.+                Cursor+                  {-# UNPACK #-} !Point+                  {-# UNPACK #-} !(Maybe a)+                  !(Radix1Tree a)++instance Show a => Show (Cursor a) where+  showsPrec d c =+    showParen (d > 10) $+      showString "Cursor " . showsPrec 11 (stop c)++cursor0 :: RadixTree a -> Cursor a+cursor0 (RadixTree mx t) = Cursor Seam mx t++cursor1 :: Radix1Tree a -> Cursor a+cursor1 = Cursor Seam Nothing++{-# INLINE move0 #-}+move0 :: Feed -> Cursor a -> Cursor a+move0 (Feed feed) = \c ->+  feed $ \step s ->+    case step s of+      More w z -> move_ step w z c+      Done     -> c++{-# INLINE move1 #-}+move1 :: Feed1 -> Cursor a -> Cursor a+move1 (Feed1 w feed) = feed $ \step -> move_ step w++{-# INLINE move_ #-}+move_ :: (x -> Step Word8 x) -> Word8 -> x -> Cursor a -> Cursor a+move_ step = \w s (Cursor point mx dx) ->+  case point of+    Seam        -> go w s dx+    Plane i arr -> goarr arr mx dx w s i+  where+    go w s t =+      case t of+        Bin p l r     -> go w s $ if w < p+                                    then l+                                    else r++        Tip brr my dy -> goarr brr my dy w s 0++        Nil           -> Cursor Seam Nothing Nil++    goarr arr mx dx = goarr_+      where+        goarr_ w s n+          | w == indexByteArray arr n =+              let !n' = n + 1+              in case step s of+                   More v z+                     | n' >= sizeofByteArray arr -> go v z dx+                     | otherwise                 -> goarr_ v z n'++                   Done      ->+                     let !point'+                           | n' >= sizeofByteArray arr = Seam+                           | otherwise                 = Plane n' arr++                     in Cursor point' mx dx++          | otherwise = Cursor Seam Nothing Nil++-- | \(\mathcal{O}(1)\).+--   Retrieve the value at which the cursor points.+stop :: Cursor a -> Maybe a+stop (Cursor point mx _) =+  case point of+    Seam -> mx+    _    -> Nothing++-- | \(\mathcal{O}(1)\).+--   Determine whether the cursor points to a point within the tree.+locate :: Cursor a -> Location+locate (Cursor _ Nothing Nil) = Outside+locate _                      = Inside++++{-# INLINE lookupL0 #-}+lookupL0 :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)+lookupL0 openness (Feed feed) (RadixTree mx t) =+  feed $ \step s ->+    case step s of+      More w z ->+        let l = lookupL_ (\b arr -> Lookup (Build $ Snoc b arr)) openness step w z t+        in case l of+             Just _  -> l+             Nothing ->+               case mx of+                 Just x  -> Just $ Lookup (Build Lin) x+                 Nothing -> Nothing++      _        ->+        case openness of+          Open   -> Nothing+          Closed -> case mx of+                      Just x  -> Just $ Lookup (Build Lin) x+                      Nothing -> Nothing++{-# INLINE lookupL1 #-}+lookupL1 :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)+lookupL1 openness (Feed1 w feed) =+  feed $ \step -> lookupL_ (\b arr -> Lookup1 (Build1 (b :/ arr))) openness step w++{-# INLINE lookupL_ #-}+lookupL_+  :: (Tsil ByteArray -> ByteArray -> a -> b)+  -> Openness -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Maybe b+lookupL_ f openness step = go Lin Nothing+  where+    getMax b t =+      let !(# b', arr, a #) = unsafeLookupMaxWithKey_ b t+      in Just $! f b' arr a++    go b getL !w !s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go b getL w s l+                   else getL++            else if w <= upper p+                   then go b (getMax b l) w s r+                   else getMax b r++        Tip arr mx dx -> goarr w s 0+          where+            getThis = f b arr `fmap'` mx++            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          let getL' = getThis <|> getL+                          in case step z of+                               More u z' -> go (Snoc b arr) getL' u z' dx+                               Done      ->+                                 case openness of+                                   Open   -> getL+                                   Closed -> getL'++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> getL++                   LT -> case dx of+                           Nil -> getThis+                           _   -> getMax (Snoc b arr) dx++                   GT -> getL++        Nil -> getL++++{-# INLINE lookupR0 #-}+lookupR0 :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)+lookupR0 openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+        lookupR_ (\b arr -> Lookup (Build $ Snoc b arr)) openness step w z t++      _        ->+        case openness of+          Closed | Just x <- mx -> Just $ Lookup (Build Lin) x++          _      -> case t of+                      Nil -> Nothing+                      _   -> let !(# b, arr, x #) = unsafeLookupMinWithKey_ Lin t+                             in Just $! Lookup (Build $ Snoc b arr) x++{-# INLINE lookupR1 #-}+lookupR1 :: Openness -> Feed1 -> Radix1Tree a -> Maybe (Lookup1 a)+lookupR1 openness (Feed1 w feed) =+  feed $ \step -> lookupR_ (\b arr -> Lookup1 (Build1 (b :/ arr))) openness step w++{-# INLINE lookupR_ #-}+lookupR_+  :: (Tsil ByteArray -> ByteArray -> a -> b)+  -> Openness -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Maybe b+lookupR_ f openness step = go Lin Nothing+  where+    getMin b t =+      let !(# b', arr, a #) = unsafeLookupMinWithKey_ b t+      in Just $! f b' arr a++    go b getR w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go b (getMin b r) w s l+                   else getMin b l++            else if w <= upper p+                   then go b getR w s r+                   else getR++        Tip arr mx dx -> goarr w s 0+          where+            getThis = f b arr `fmap'` mx++            getBelow =+              case dx of+                Nil -> Nothing+                _   -> getMin (Snoc b arr) dx++            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> go (Snoc b arr) getR u z' dx+                            Done      ->+                                  ( case openness of+                                      Open   -> getBelow+                                      Closed -> getThis <|> getBelow+                                  )+                              <|> getR++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> (getThis <|> getBelow) <|> getR++                   GT -> getThis <|> getBelow++                   LT -> getR++        Nil -> getR++++{-# INLINE adjustL0 #-}+adjustL0 :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustL0 f openness (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree (f <$> mx) $ adjustL_ f openness step w z t+      Done     ->+        case openness of+          Open   -> t0+          Closed -> case mx of+                      Just x  -> RadixTree (Just $ f x) t+                      Nothing -> t0++{-# INLINE adjustL1 #-}+adjustL1 :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustL1 f openness (Feed1 w feed) =+  feed $ \step -> adjustL_ f openness step w++{-# INLINE adjustL_ #-}+adjustL_+  :: (a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustL_ f openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go w s l) r+                   else t++            else if w <= upper p+                   then Bin p (map1 f l) (go w s r)+                   else map1 f t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr (f <$> mx) $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f <$> mx++                              in Tip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   LT -> map1 f t++                   GT -> t++        Nil -> Nil++++{-# INLINE adjustL0' #-}+adjustL0' :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustL0' f openness (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree (f `fmap'` mx) $ adjustL'_ f openness step w z t+      Done     ->+        case openness of+          Open   -> t0+          Closed -> case mx of+                      Just x  -> RadixTree (Just $! f x) t+                      Nothing -> t0++{-# INLINE adjustL1' #-}+adjustL1' :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustL1' f openness (Feed1 w feed) =+  feed $ \step -> adjustL'_ f openness step w++{-# INLINE adjustL'_ #-}+adjustL'_+  :: (a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustL'_ f openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go w s l) r+                   else t++            else if w <= upper p+                   then Bin p (map1' f l) (go w s r)+                   else map1' f t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr (f `fmap'` mx) $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f `fmap'` mx++                              in Tip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   LT -> map1' f t++                   GT -> t++        Nil -> Nil++++{-# INLINE adjustLWithKey0 #-}+adjustLWithKey0 :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustLWithKey0 f openness (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree (f (Build Lin) <$> mx) $+                    adjustLWithKey_ (\b arr -> f (Build $ Snoc b arr)) openness step w z t+      Done     ->+        case openness of+          Open   -> t0+          Closed -> RadixTree (f (Build Lin) <$> mx) t++{-# INLINE adjustLWithKey1 #-}+adjustLWithKey1 :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustLWithKey1 f openness (Feed1 w feed) =+  feed $ \step -> adjustLWithKey_ (\b arr -> f (Build1 $ b :/ arr)) openness step w++{-# INLINE adjustLWithKey_ #-}+adjustLWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustLWithKey_ f openness step = go Lin+  where+    go b w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go b w s l) r+                   else t++            else if w <= upper p+                   then Bin p (mapWithKey_ f b l) (go b w s r)+                   else mapWithKey_ f b t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr (f b arr <$> mx) $+                                           go (Snoc b arr) u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f b arr <$> mx++                              in Tip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   LT -> mapWithKey_ f b t++                   GT -> t++        Nil -> Nil++++{-# INLINE adjustLWithKey0' #-}+adjustLWithKey0' :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustLWithKey0' f openness (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+        RadixTree (f (Build Lin) `fmap'` mx) $+          adjustLWithKey'_ (\b arr -> f (Build $ Snoc b arr)) openness step w z t++      Done     ->+        case openness of+          Open   -> t0+          Closed -> case mx of+                      Just x  -> RadixTree (Just $! f (Build Lin) x) t+                      Nothing -> t0++{-# INLINE adjustLWithKey1' #-}+adjustLWithKey1'+  :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustLWithKey1' f openness (Feed1 w feed) =+  feed $ \step -> adjustLWithKey'_ (\b arr -> f (Build1 $ b :/ arr)) openness step w++{-# INLINE adjustLWithKey'_ #-}+adjustLWithKey'_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustLWithKey'_ f openness step = go Lin+  where+    go b w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go b w s l) r+                   else t++            else if w <= upper p+                   then Bin p (mapWithKey'_ f b l) (go b w s r)+                   else mapWithKey'_ f b t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr (f b arr `fmap'` mx) $+                                           go (Snoc b arr) u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f b arr `fmap'` mx++                              in Tip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   LT -> mapWithKey'_ f b t++                   GT -> t++        Nil -> Nil++++{-# INLINE adjustR0 #-}+adjustR0 :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustR0 f openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ adjustR_ f openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> f <$> mx++        in RadixTree my (map1 f t)++{-# INLINE adjustR1 #-}+adjustR1 :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustR1 f openness (Feed1 w feed) =+  feed $ \step -> adjustR_ f openness step w++{-# INLINE adjustR_ #-}+adjustR_+  :: (a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustR_ f openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go w s l) (map1 f r)+                   else map1 f t++            else if w <= upper p+                   then Bin p l (go w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr mx $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f <$> mx++                              in Tip arr my $ map1 f dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> map1 f t++                   GT -> map1 f t++                   LT -> t++        Nil -> Nil++++{-# INLINE adjustR0' #-}+adjustR0' :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustR0' f openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ adjustR'_ f openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> f `fmap'` mx++        in RadixTree my (map1' f t)++{-# INLINE adjustR1' #-}+adjustR1' :: (a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustR1' f openness (Feed1 w feed) =+  feed $ \step -> adjustR'_ f openness step w++{-# INLINE adjustR'_ #-}+adjustR'_+  :: (a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustR'_ f openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go w s l) (map1' f r)+                   else map1' f t++            else if w <= upper p+                   then Bin p l (go w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr mx $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f `fmap'` mx++                              in Tip arr my $ map1' f dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> map1 f t++                   GT -> map1' f t++                   LT -> t++        Nil -> Nil++++{-# INLINE adjustRWithKey0 #-}+adjustRWithKey0 :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustRWithKey0 f openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+       RadixTree mx $+         adjustRWithKey_ (\b arr -> f (Build $ Snoc b arr)) openness step w z t++      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> f (Build Lin) <$> mx++        in RadixTree my $ mapWithKey_ (\b arr -> f (Build $ Snoc b arr)) Lin t++{-# INLINE adjustRWithKey1 #-}+adjustRWithKey1 :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustRWithKey1 f openness (Feed1 w feed) =+  feed $ \step -> adjustRWithKey_ (\b arr -> f (Build1 $ b :/ arr)) openness step w++{-# INLINE adjustRWithKey_ #-}+adjustRWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustRWithKey_ f openness step = go Lin+  where+    go b w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go b w s l) (mapWithKey_ f b r)+                   else mapWithKey_ f b t++            else if w <= upper p+                   then Bin p l (go b w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr mx $ go (Snoc b arr) u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f b arr <$> mx++                              in Tip arr my $ mapWithKey_ f (Snoc b arr) dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> mapWithKey_ f b t++                   GT -> mapWithKey_ f b t++                   LT -> t++        Nil -> Nil++++{-# INLINE adjustRWithKey0' #-}+adjustRWithKey0' :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustRWithKey0' f openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+        RadixTree mx $+          adjustRWithKey'_ (\b arr -> f (Build $ Snoc b arr)) openness step w z t++      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> f (Build Lin) `fmap'` mx++        in RadixTree my $ mapWithKey'_ (\b arr -> f (Build $ Snoc b arr)) Lin t++{-# INLINE adjustRWithKey1' #-}+adjustRWithKey1'+  :: (Build1 -> a -> a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjustRWithKey1' f openness (Feed1 w feed) =+  feed $ \step -> adjustRWithKey'_ (\b arr -> f (Build1 $ b :/ arr)) openness step w++{-# INLINE adjustRWithKey'_ #-}+adjustRWithKey'_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjustRWithKey'_ f openness step = go Lin+  where+    go b w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then Bin p (go b w s l) (mapWithKey'_ f b r)+                   else mapWithKey'_ f b t++            else if w <= upper p+                   then Bin p l (go b w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> Tip arr mx $ go (Snoc b arr) u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f b arr `fmap'` mx++                              in Tip arr my $ mapWithKey'_ f (Snoc b arr) dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> mapWithKey'_ f b t++                   GT -> mapWithKey'_ f b t++                   LT -> t++        Nil -> Nil++++{-# INLINE updateL0 #-}+updateL0 :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateL0 f openness (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree (f =<< mx) $ updateL_ f openness step w z t+      Done     ->+        case openness of+          Open   -> t0+          Closed -> RadixTree (f =<< mx) t++{-# INLINE updateL1 #-}+updateL1 :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateL1 f openness (Feed1 w feed) =+  feed $ \step -> updateL_ f openness step w++{-# INLINE updateL_ #-}+updateL_+  :: (a -> Maybe a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+updateL_ f openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go w s l) r+                   else t++            else if w <= upper p+                   then rebin p (mapMaybe1 f l) (go w s r)+                   else mapMaybe1 f t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr (f =<< mx) $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f =<< mx++                              in retip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   LT -> mapMaybe1 f t++                   GT -> t++        Nil -> Nil++++{-# INLINE updateLWithKey0 #-}+updateLWithKey0+  :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateLWithKey0 f openness (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+        RadixTree (f (Build Lin) =<< mx) $+          updateLWithKey_ (\b arr -> f (Build $ Snoc b arr)) openness step w z t++      Done     ->+        case openness of+          Open   -> t0+          Closed -> RadixTree (f (Build Lin) =<< mx) t++{-# INLINE updateLWithKey1 #-}+updateLWithKey1+  :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateLWithKey1 f openness (Feed1 w feed) =+  feed $ \step -> updateLWithKey_ (\b arr -> f (Build1 $ b :/ arr)) openness step w++{-# INLINE updateLWithKey_ #-}+updateLWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Maybe a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+updateLWithKey_ f openness step = go Lin+  where+    go b w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go b w s l) r+                   else t++            else if w <= upper p+                   then rebin p (mapMaybeWithKey_ f b l) (go b w s r)+                   else mapMaybeWithKey_ f b t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr (f b arr =<< mx) $+                                           go (Snoc b arr) u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f b arr =<< mx++                              in retip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   LT -> mapMaybeWithKey_ f b t++                   GT -> t++        Nil -> Nil++++{-# INLINE updateR0 #-}+updateR0 :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateR0 f openness (Feed feed) (RadixTree mx t) =+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ updateR_ f openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> f =<< mx++        in RadixTree my (mapMaybe1 f t)++{-# INLINE updateR1 #-}+updateR1 :: (a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateR1 f openness (Feed1 w feed) =+  feed $ \step -> updateR_ f openness step w++{-# INLINE updateR_ #-}+updateR_+  :: (a -> Maybe a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+updateR_ f openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebin p (go w s l) (mapMaybe1 f r)+                   else mapMaybe1 f t++            else if w <= upper p+                   then rebinR p l (go w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr mx $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f =<< mx++                              in retip arr my $ mapMaybe1 f dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> mapMaybe1 f t++                   GT -> mapMaybe1 f t++                   LT -> t++        Nil -> Nil++++{-# INLINE updateRWithKey0 #-}+updateRWithKey0+  :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateRWithKey0 f openness (Feed feed) (RadixTree mx t) =+  feed $ \step s ->+    case step s of+      More w z ->+        RadixTree mx $+          updateRWithKey_ (\b arr -> f (Build $ Snoc b arr)) openness step w z t++      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> f (Build Lin) =<< mx++        in RadixTree my (mapMaybeWithKey_ (\b arr -> f (Build $ Snoc b arr)) Lin t)++{-# INLINE updateRWithKey1 #-}+updateRWithKey1+  :: (Build1 -> a -> Maybe a) -> Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+updateRWithKey1 f openness (Feed1 w feed) =+  feed $ \step -> updateRWithKey_ (\b arr -> f (Build1 $ b :/ arr)) openness step w++{-# INLINE updateRWithKey_ #-}+updateRWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Maybe a) -> Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+updateRWithKey_ f openness step = go Lin+  where+    go b w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebin p (go b w s l) (mapMaybeWithKey_ f b r)+                   else mapMaybeWithKey_ f b t++            else if w <= upper p+                   then rebinR p l (go b w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr mx $ go (Snoc b arr) u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> mx+                                         Closed -> f b arr =<< mx++                              in retip arr my $ mapMaybeWithKey_ f (Snoc b arr) dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> mapMaybeWithKey_ f b t++                   GT -> mapMaybeWithKey_ f b t++                   LT -> t++        Nil -> Nil++++{-# INLINE takeL0 #-}+takeL0 :: Openness -> Feed -> RadixTree a -> RadixTree a+takeL0 openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ takeL_ openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> Nothing+                   Closed -> mx++        in RadixTree my Nil++{-# INLINE takeL1 #-}+takeL1 :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+takeL1 openness (Feed1 w0 feed) = feed $ \step -> takeL_ openness step w0++{-# INLINE takeL_ #-}+takeL_ :: Openness -> (x -> Step Prefix x) -> Prefix -> x -> Radix1Tree a -> Radix1Tree a+takeL_ openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go w s l+                   else Nil++            else if w <= upper p+                   then rebinR p l (go w s r)+                   else t++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr mx $ go u z' dx+                            Done      ->+                              case openness of+                                Open   -> Nil+                                Closed -> retip arr mx Nil++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> Nil++                   LT -> t++                   GT -> Nil++        Nil -> Nil++++{-# INLINE takeR0 #-}+takeR0 :: Openness -> Feed -> RadixTree a -> RadixTree a+takeR0 openness (Feed feed) (RadixTree mx t) =+  feed $ \step s ->+    case step s of+      More w z -> RadixTree Nothing $ takeR_ openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> Nothing+                   Closed -> mx++        in RadixTree my t++{-# INLINE takeR1 #-}+takeR1 :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+takeR1 openness (Feed1 w0 feed) = feed $ \step -> takeR_ openness step w0++{-# INLINE takeR_ #-}+takeR_ :: Openness -> (x -> Step Prefix x) -> Prefix -> x -> Radix1Tree a -> Radix1Tree a+takeR_ openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go w s l) r+                   else t++            else if w <= upper p+                   then go w s r+                   else Nil++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' -> retip arr Nothing $ go u z' dx+                            Done      ->+                              let my = case openness of+                                         Open   -> Nothing+                                         Closed -> mx++                              in retip arr my dx++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> t++                   GT -> t++                   LT -> Nil++        Nil -> Nil++++type UBin a = (# Prefix, Radix1Tree a, Radix1Tree a #)++type UTip a = (# Key, Int, ByteArray, Maybe a, Radix1Tree a #)++++union0 :: RadixTree a -> RadixTree a -> RadixTree a+union0 (RadixTree mA tA) (RadixTree mB tB) = RadixTree (mA <|> mB) (union1 tA tB)++union1 :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+union1 = anyAny+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA    -> binAny (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> tB++    tipAny uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip uA tA uB tB lenA+                                else tipTip uB tB uA tA lenB++        Nil             | nA == 0   -> tA+                        | otherwise -> Tip (dropByteArray nA arrA) mA dA++    tipTip (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then Tip arrA' (mA <|> mB) (anyAny dA dB)+                             else Tip arrA' mA $+                                    tipAny (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | o == 1 =+              let !tA' | nA == 0   = tA+                       | otherwise = Tip (dropByteArray nA arrA) mA dA++                  !tB' | nB == 0   = tB+                       | otherwise = Tip (dropByteArray nB arrB) mB dB++              in join wA tA' wB tB'++          | otherwise =+              let !o' = o - 1++                  !(# !arrC, !arrA' #) = splitByteArray nA o' arrA++                  !arrB' = dropByteArray (nB + o') arrB++              in Tip arrC Nothing $ join wA (Tip arrA' mA dA)+                                         wB (Tip arrB' mB dB)++    binAny uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0+                           in tipBin (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> tA++    tipBin uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = let !tA' | nA == 0   = tA+                                | otherwise = Tip (dropByteArray nA arrA) mA dA++                       in join wA tA' pB tB++      | wA < pB      = Bin pB (tipAny uA tA lB) rB+      | otherwise    = Bin pB lB (tipAny uA tA rB)++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = join pA tA pB tB++      in case Prelude.compare pA pB of+           EQ                  -> Bin pA (anyAny lA lB) (anyAny rA rB)++           LT | pB <= upper pA -> Bin pA lA (binAny uB tB rA)+              | pA >= lower pB -> Bin pB (binAny uA tA lB) rB+              | otherwise      -> no++           GT | pA <= upper pB -> Bin pB lB (binAny uA tA rB)+              | pB >= lower pA -> Bin pA (binAny uB tB lA) rA+              | otherwise      -> no++++unionL0 :: RadixTree a -> RadixTree a -> RadixTree a+unionL0 (RadixTree mA tA) (RadixTree mB tB) = RadixTree (mA <|> mB) (unionL1 tA tB)++unionL1 :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionL1 =+  union_ $ \s a b ->+    let !(# c #) = case s of+                     L -> (# a #)+                     R -> (# b #)+    in Just c+++unionWith0' :: (a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a+unionWith0' f (RadixTree mA tA) (RadixTree mB tB) =+  let mC = case mA of+             Just a  -> case mB of+                          Just b  -> Just $! f a b+                          Nothing -> mA++             Nothing -> mB++  in RadixTree mC (unionWith1' f tA tB)++unionWith1' :: (a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionWith1' f =+  union_ $ \s a b ->+    Just $! case s of+              L -> f a b+              R -> f b a++++{-# INLINE union_ #-}+union_+  :: (forall x y. S x y a a -> x -> y -> Maybe a)+  -> Radix1Tree a+  -> Radix1Tree a+  -> Radix1Tree a+union_ f = anyAny L+  where+    anyAny s tA tB =+      case tA of+        Bin pA lA rA    -> binAny s (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> tB++    tipAny s uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s uA tA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' uB tB uA tA lenB++        Nil             | nA == 0   -> tA+                        | otherwise -> Tip (dropByteArray nA arrA) mA dA++    tipTip s (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC = case mA of+                                             Just a  -> case mB of+                                                          Just b  -> f s a b+                                                          Nothing -> mA++                                             Nothing -> mB++                                  in Tip arrA' mC (anyAny s dA dB)++                             else Tip arrA' mA $+                                    let !(# s' #) = other s+                                    in tipAny s' (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | o == 1 =+              let !tA' | nA == 0   = tA+                       | otherwise = Tip (dropByteArray nA arrA) mA dA++                  !tB' | nB == 0   = tB+                       | otherwise = Tip (dropByteArray nB arrB) mB dB++              in join wA tA' wB tB'++          | otherwise =+              let !o' = o - 1++                  !(# !arrC, !arrA' #) = splitByteArray nA o' arrA++                  !arrB' = dropByteArray (nB + o') arrB++              in Tip arrC Nothing $ join wA (Tip arrA' mA dA)+                                         wB (Tip arrB' mB dB)++    binAny s uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> tA++    tipBin s uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = let !tA' | nA == 0   = tA+                                | otherwise = Tip (dropByteArray nA arrA) mA dA++                       in join wA tA' pB tB++      | wA < pB      = Bin pB (tipAny s uA tA lB) rB+      | otherwise    = Bin pB lB (tipAny s uA tA rB)++    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = join pA tA pB tB++      in case Prelude.compare pA pB of+           EQ                  -> Bin pA (anyAny s lA lB) (anyAny s rA rB)++           LT | pB <= upper pA -> let !(# s' #) = other s+                                  in Bin pA lA (binAny s' uB tB rA)+              | pA >= lower pB -> Bin pB (binAny s uA tA lB) rB+              | otherwise      -> no++           GT | pA <= upper pB -> Bin pB lB (binAny s uA tA rB)+              | pB >= lower pA -> let !(# s' #) = other s+                                  in Bin pA (binAny s' uB tB lA) rA+              | otherwise      -> no+++++unionWithKey0' :: (Build -> a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a+unionWithKey0' f (RadixTree mA tA) (RadixTree mB tB) =+  let mC = case mA of+             Just a  -> case mB of+                          Just b  -> Just $! f (Build Lin) a b+                          Nothing -> mA++             Nothing -> mB++  in RadixTree mC $ unionWithKey_+                      ( \s b arr vA vB ->+                           Just $! let b0 = Build $ Snoc b arr+                                   in case s of+                                        L -> f b0 vA vB+                                        R -> f b0 vB vA+                      )+                      tA tB++unionWithKey1' :: (Build1 -> a -> a -> a) -> Radix1Tree a -> Radix1Tree a -> Radix1Tree a+unionWithKey1' f =+  unionWithKey_ $ \s b arr vA vB ->+    Just $! let b1 = Build1 $ b :/ arr+            in case s of+                 L -> f b1 vA vB+                 R -> f b1 vB vA++{-# INLINE unionWithKey_ #-}+unionWithKey_+  :: (forall x y. S x y a a -> Tsil ByteArray -> ByteArray -> x -> y -> Maybe a)+  -> Radix1Tree a+  -> Radix1Tree a+  -> Radix1Tree a+unionWithKey_ f = anyAny L Lin+  where+    anyAny s b tA tB =+      case tA of+        Bin pA lA rA    -> binAny s b (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s b (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> tB++    tipAny s b uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s b uA tA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' b uB tB uA tA lenB++        Nil             | nA == 0   -> tA+                        | otherwise -> Tip (dropByteArray nA arrA) mA dA++    tipTip s b (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC =+                                        case mA of+                                          Just xA ->+                                            case mB of+                                              Just xB -> f s b arrA' xA xB+                                              Nothing -> mA++                                          Nothing -> mB++                                  in Tip arrA' mC (anyAny s (Snoc b arrA') dA dB)++                             else Tip arrA' mA $+                                    let !(# s' #) = other s+                                    in tipAny s' (Snoc b arrA')+                                         (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | o == 1 =+              let !tA' | nA == 0   = tA+                       | otherwise = Tip (dropByteArray nA arrA) mA dA++                  !tB' | nB == 0   = tB+                       | otherwise = Tip (dropByteArray nB arrB) mB dB++              in join wA tA' wB tB'++          | otherwise =+              let !o' = o - 1++                  !(# !arrC, !arrA' #) = splitByteArray nA o' arrA++                  !arrB' = dropByteArray (nB + o') arrB++              in Tip arrC Nothing $ join wA (Tip arrA' mA dA)+                                         wB (Tip arrB' mB dB)++    binAny s b uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' b (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> tA++    tipBin s b uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = let !tA' | nA == 0   = tA+                                | otherwise = Tip (dropByteArray nA arrA) mA dA++                       in join wA tA' pB tB++      | wA < pB      = Bin pB (tipAny s b uA tA lB) rB+      | otherwise    = Bin pB lB (tipAny s b uA tA rB)++    binBin s b uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = join pA tA pB tB++      in case Prelude.compare pA pB of+           EQ                  -> Bin pA (anyAny s b lA lB) (anyAny s b rA rB)++           LT | pB <= upper pA -> let !(# s' #) = other s+                                  in Bin pA lA (binAny s' b uB tB rA)+              | pA >= lower pB -> Bin pB (binAny s b uA tA lB) rB+              | otherwise      -> no++           GT | pA <= upper pB -> Bin pB lB (binAny s b uA tA rB)+              | pB >= lower pA -> let !(# s' #) = other s+                                  in Bin pA (binAny s' b uB tB lA) rA+              | otherwise      -> no++++difference0 :: RadixTree a -> RadixTree b -> RadixTree a+difference0 (RadixTree mA tA) (RadixTree mB tB) =+  let mC = case mB of+             Just _  -> Nothing+             Nothing -> mA++  in RadixTree mC $ difference1 tA tB++difference1 :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a+difference1 =+  difference_ $ \_ _ _ ->+    Nothing+++differenceWith0+  :: (a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a+differenceWith0 f (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just xA <- mA, Just xB <- mB = f xA xB+         | otherwise                    = mA++  in RadixTree mC $ differenceWith1 f tA tB++differenceWith1+  :: (a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a+differenceWith1 f =+  difference_ $ \s xA xB ->+    case s of+      L -> f xA xB+      R -> f xB xA++{-# INLINE difference_ #-}+difference_+  :: (forall x y. S x y a b -> x -> y -> Maybe a)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree a+difference_ (f :: forall n o. S n o x y -> n -> o -> Maybe x) = anyAny L+  where+    anyAny :: forall a b. S a b x y -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    anyAny s tA tB =+      case tA of+        Bin pA lA rA    -> binAny s (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> case s of+                             L -> Nil+                             R -> tB++    tipAny+      :: forall a b. S a b x y -> UTip a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    tipAny s uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s uA tA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' uB tB uA tA lenB++        Nil             -> case s of+                             L | nA == 0   -> tA+                               | otherwise -> Tip (dropByteArray nA arrA) mA dA++                             R -> Nil++    tipTip+      :: forall a b. S a b x y+      -> UTip a -> Radix1Tree a -> UTip b -> Radix1Tree b -> Int -> Radix1Tree x+    tipTip s (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC | Just xA <- mA, Just xB <- mB = f s xA xB+                                         | otherwise =+                                             case s of+                                               L -> mA+                                               R -> mB++                                  in retip arrA' mC (anyAny s dA dB)++                             else let mA' = case s of+                                              L -> mA+                                              R -> Nothing++                                  in retip arrA' mA' $+                                       let !(# s' #) = other s+                                       in tipAny s' (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise =+              case s of+                L | nA == 0   -> tA+                  | otherwise -> Tip (dropByteArray nA arrA) mA dA++                R | nB == 0   -> tB+                  | otherwise -> Tip (dropByteArray nB arrB) mB dB++    binAny+      :: forall a b. S a b x y -> UBin a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> case s of+                             L -> tA+                             R -> tB++    tipBin+      :: forall a b. S a b x y+      -> UTip a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree x+    tipBin s uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = case s of+                         L | nA == 0   -> tA+                           | otherwise -> Tip (dropByteArray nA arrA) mA dA++                         R -> tB++      | wA < pB      = case s of+                         L -> tipAny s uA tA lB+                         R -> rebinL pB (tipAny s uA tA lB) rB++      | otherwise    = case s of+                         L -> tipAny s uA tA rB+                         R -> rebinR pB lB (tipAny s uA tA rB)++    binBin+      :: forall a b. S a b x y+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree x+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let no = case s of+                 L -> tA+                 R -> tB++      in case Prelude.compare pA pB of+           EQ                  -> rebin pA (anyAny s lA lB) (anyAny s rA rB)++           LT | pB <= upper pA -> case s of+                                    L -> rebinR pA lA (binAny R uB tB rA)+                                    R -> binAny L uB tB rA++              | pA >= lower pB -> case s of+                                    L -> binAny s uA tA lB+                                    R -> rebinL pB (binAny s uA tA lB) rB++              | otherwise      -> no++           GT | pA <= upper pB -> case s of+                                    L -> binAny s uA tA rB+                                    R -> rebinR pB lB (binAny s uA tA rB)++              | pB >= lower pA -> case s of+                                    L -> rebinL pA (binAny R uB tB lA) rA+                                    R -> binAny L uB tB lA++              | otherwise      -> no++++differenceWithKey0+  :: (Build -> a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a+differenceWithKey0 f (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just xA <- mA, Just xB <- mB = f (Build Lin) xA xB+         | otherwise                    = mA++  in RadixTree mC $ differenceWithKey_+                      ( \s b arr xA xB ->+                           let b0 = Build $ Snoc b arr+                           in case s of+                                L -> f b0 xA xB+                                R -> f b0 xB xA+                      )+                      tA tB++differenceWithKey1+  :: (Build1 -> a -> b -> Maybe a) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree a+differenceWithKey1 f =+  differenceWithKey_ $ \s b arr xA xB ->+    let b1 = Build1 $ b :/ arr+    in case s of+         L -> f b1 xA xB+         R -> f b1 xB xA++{-# INLINE differenceWithKey_ #-}+differenceWithKey_+  :: (forall x y. S x y a b -> Tsil ByteArray -> ByteArray -> x -> y -> Maybe a)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree a+differenceWithKey_+  (f :: forall n o. S n o x y -> Tsil ByteArray -> ByteArray -> n -> o -> Maybe x) =+    anyAny L Lin+  where+    anyAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    anyAny s b tA tB =+      case tA of+        Bin pA lA rA    -> binAny s b (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s b (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> case s of+                             L -> Nil+                             R -> tB++    tipAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    tipAny s b uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s b uA tA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' b uB tB uA tA lenB++        Nil             -> case s of+                             L | nA == 0   -> tA+                               | otherwise -> Tip (dropByteArray nA arrA) mA dA++                             R -> Nil++    tipTip+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> UTip b -> Radix1Tree b -> Int -> Radix1Tree x+    tipTip s b (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC | Just xA <- mA, Just xB <- mB =+                                             f s b arrA' xA xB++                                         | otherwise =+                                             case s of+                                               L -> mA+                                               R -> mB++                                  in retip arrA' mC (anyAny s (Snoc b arrA') dA dB)++                             else let mA' = case s of+                                              L -> mA+                                              R -> Nothing++                                  in retip arrA' mA' $+                                       let !(# s' #) = other s+                                       in tipAny s' (Snoc b arrA')+                                            (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise =+              case s of+                L | nA == 0   -> tA+                  | otherwise -> Tip (dropByteArray nA arrA) mA dA++                R | nB == 0   -> tB+                  | otherwise -> Tip (dropByteArray nB arrB) mB dB++    binAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree x+    binAny s b uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' b (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> case s of+                             L -> tA+                             R -> tB++    tipBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree x+    tipBin s b uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = case s of+                         L | nA == 0   -> tA+                           | otherwise -> Tip (dropByteArray nA arrA) mA dA++                         R -> tB++      | wA < pB      = case s of+                         L -> tipAny s b uA tA lB+                         R -> rebinL pB (tipAny s b uA tA lB) rB++      | otherwise    = case s of+                         L -> tipAny s b uA tA rB+                         R -> rebinR pB lB (tipAny s b uA tA rB)++    binBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree x+    binBin s b uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let no = case s of+                 L -> tA+                 R -> tB++      in case Prelude.compare pA pB of+           EQ                  -> rebin pA (anyAny s b lA lB) (anyAny s b rA rB)++           LT | pB <= upper pA -> case s of+                                    L -> rebinR pA lA (binAny R b uB tB rA)+                                    R -> binAny L b uB tB rA++              | pA >= lower pB -> case s of+                                    L -> binAny s b uA tA lB+                                    R -> rebinL pB (binAny s b uA tA lB) rB++              | otherwise      -> no++           GT | pA <= upper pB -> case s of+                                    L -> binAny s b uA tA rB+                                    R -> rebinR pB lB (binAny s b uA tA rB)++              | pB >= lower pA -> case s of+                                    L -> rebinL pA (binAny R b uB tB lA) rA+                                    R -> binAny L b uB tB lA++              | otherwise      -> no++++compare0 :: (a -> b -> Bool) -> RadixTree a -> RadixTree b -> PartialOrdering+compare0 f (RadixTree mA tA) (RadixTree mB tB) =+  let o = case mA of+            Just xA -> case mB of+                         Just xB+                           | f xA xB   -> Equal+                           | otherwise -> Incomparable++                         Nothing -> Superset++            Nothing -> case mB of+                         Just _  -> Subset+                         Nothing -> Equal++  in order o $ Data.RadixNTree.Word8.Strict.compare1 f tA tB++compare1 :: (a -> b -> Bool) -> Radix1Tree a -> Radix1Tree b -> PartialOrdering+compare1 (f :: x -> y -> Bool) = anyAny L+  where+    anyAny :: forall a b. S a b x y -> Radix1Tree a -> Radix1Tree b -> PartialOrdering+    anyAny s tA tB =+      case tA of+        Bin pA lA rA    -> binAny s (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> case tB of+                             Nil -> Equal+                             _   -> case s of+                                      L -> Subset+                                      R -> Superset++    tipAny+      :: forall a b. S a b x y -> UTip a -> Radix1Tree a -> Radix1Tree b -> PartialOrdering+    tipAny s uA@(# _, nA, arrA, _, _ #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s uA tA (# pB, lB, rB #)++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s uA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' uB uA tA lenB++        Nil             -> case s of+                             L -> Superset+                             R -> Subset++    tipTip+      :: forall a b. S a b x y -> UTip a -> UTip b -> Radix1Tree b -> Int -> PartialOrdering+    tipTip s (# wA0, nA, arrA, mA, dA #) (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then if nB' == sizeofByteArray arrB+                          then let o_ = case mA of+                                          Just xA -> case mB of+                                                       Just xB ->+                                                         let eq = case s of+                                                                    L -> f xA xB+                                                                    R -> f xB xA++                                                         in if eq+                                                              then Equal+                                                              else Incomparable++                                                       Nothing -> case s of+                                                                    L -> Superset+                                                                    R -> Subset+                                          Nothing -> case mB of+                                                       Just _  -> case s of+                                                                    L -> Subset+                                                                    R -> Superset++                                                       Nothing -> Equal++                               in order o_ $ anyAny s dA dB++                          else let !(# s' #) = other s+                               in tipAny s' (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise = case s of+                             L -> Superset+                             R -> Subset++    binAny+      :: forall a b. S a b x y -> UBin a -> Radix1Tree a -> Radix1Tree b -> PartialOrdering+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' (# wB, 0, arrB, mB, dB #) tB uA++        Nil             -> case s of+                             L -> Superset+                             R -> Subset++    tipBin :: forall a b. S a b x y -> UTip a -> Radix1Tree a -> UBin b -> PartialOrdering+    tipBin s uA@(# wA, _, _, _, _ #) tA (# pB, lB, rB #)+      | beyond pB wA = Incomparable+      | otherwise    = limit s . tipAny s uA tA $ if wA < pB+                                                     then lB+                                                     else rB++    binBin+      :: forall a b. S a b x y+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> PartialOrdering+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> order (anyAny s lA lB) (anyAny s rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s+                               in limit s' $ binAny s' uB tB rA+           | pA >= lower pB -> limit s $ binAny s uA tA lB+           | otherwise      -> Incomparable++        GT | pA <= upper pB -> limit s $ binAny s uA tA rB+           | pB >= lower pA -> let !(# s' #) = other s+                               in limit s' $ binAny s' uB tB lA+           | otherwise      -> Incomparable++++disjoint0 :: RadixTree a -> RadixTree b -> Bool+disjoint0 (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just _ <- mA, Just _ <- mB = False+         | otherwise                  = True++  in mC && disjoint1 tA tB++disjoint1 :: Radix1Tree a -> Radix1Tree b -> Bool+disjoint1 = anyAny+  where+    anyAny :: forall a b. Radix1Tree a -> Radix1Tree b -> Bool+    anyAny tA tB =+      case tA of+        Bin pA lA rA    -> binAny (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> True++    tipAny :: forall a b. UTip a -> Radix1Tree a -> Radix1Tree b -> Bool+    tipAny uA@(# _, nA, arrA, _, _ #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin uA tA (# pB, lB, rB #)++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip uA uB tB lenA++                                else tipTip uB uA tA lenB++        Nil             -> True++    tipTip :: forall a b. UTip a -> UTip b -> Radix1Tree b -> Int -> Bool+    tipTip (# wA0, nA, arrA, mA, dA #) (# wB0, nB, arrB, mB, dB #) tB len = go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then if nB' == sizeofByteArray arrB+                          then let mC | Just _ <- mA, Just _ <- mB = False+                                      | otherwise                  = True++                               in mC && anyAny dA dB++                          else tipAny (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise = True++    binAny :: forall a b. UBin a -> Radix1Tree a -> Radix1Tree b -> Bool+    binAny uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                           in tipBin (# wB, 0, arrB, mB, dB #) tB uA++        Nil             -> True++    tipBin :: forall a b. UTip a -> Radix1Tree a -> UBin b -> Bool+    tipBin uA@(# wA, _, _, _, _ #) tA (# pB, lB, rB #)+      | beyond pB wA = True+      | otherwise    = tipAny uA tA $ if wA < pB+                                        then lB+                                        else rB++    binBin :: forall a b. UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Bool+    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> anyAny lA lB && anyAny rA rB++        LT | pB <= upper pA -> binAny uB tB rA+           | pA >= lower pB -> binAny uA tA lB+           | otherwise      -> True++        GT | pA <= upper pB -> binAny uA tA rB+           | pB >= lower pA -> binAny uB tB lA+           | otherwise      -> True++++intersection0 :: RadixTree a -> RadixTree a -> RadixTree a+intersection0 (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just _ <- mA, Just _ <- mB = mA+         | otherwise                  = Nothing++  in RadixTree mC (intersection1 tA tB)++intersection1 :: Radix1Tree a -> Radix1Tree a -> Radix1Tree a+intersection1 = anyAny+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA    -> binAny (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> Nil++    tipAny uA@(# _, nA, arrA, _, _ #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin uA tA (# pB, lB, rB #)++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip uA uB tB lenA++                                else tipTip uB uA tA lenB++        Nil             -> Nil++    tipTip (# wA0, nA, arrA, mA, dA #) (# wB0, nB, arrB, mB, dB #) tB len = go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC | Just _ <- mA, Just _ <- mB = mA+                                         | otherwise                  = Nothing++                                  in retip arrA' mC (anyAny dA dB)++                             else retip arrA' Nothing $+                                    tipAny (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise = Nil++    binAny uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                           in tipBin (# wB, 0, arrB, mB, dB #) tB uA++        Nil             -> Nil++    tipBin uA@(# wA, _, _, _, _ #) tA (# pB, lB, rB #)+      | beyond pB wA = Nil+      | otherwise    = tipAny uA tA $ if wA < pB+                                        then lB+                                        else rB++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny lA lB) (anyAny rA rB)++        LT | pB <= upper pA -> binAny uB tB rA+           | pA >= lower pB -> binAny uA tA lB+           | otherwise      -> Nil++        GT | pA <= upper pB -> binAny uA tA rB+           | pB >= lower pA -> binAny uB tB lA+           | otherwise      -> Nil++++intersectionL0 :: RadixTree a -> RadixTree b -> RadixTree a+intersectionL0 (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just _ <- mA, Just _ <- mB = mA+         | otherwise                  = Nothing++  in RadixTree mC (intersectionL1 tA tB)++intersectionL1 :: Radix1Tree a -> Radix1Tree b -> Radix1Tree a+intersectionL1 =+  intersection_ $ \s a b ->+    let !(# c #) = case s of+                     L -> (# a #)+                     R -> (# b #)+    in Just c+++intersectionWith0' :: (a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c+intersectionWith0' f (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just a <- mA, Just b <- mB = Just $! f a b+         | otherwise                  = Nothing++  in RadixTree mC (intersectionWith1' f tA tB)++intersectionWith1' :: (a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+intersectionWith1' f =+  intersection_ $ \s a b ->+    Just $! case s of+              L -> f a b+              R -> f b a++{-# INLINE intersection_ #-}+intersection_+  :: (forall x y. S x y a b -> x -> y -> Maybe c)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree c+intersection_ (f :: forall n o. S n o x y -> n -> o -> Maybe c) = anyAny L+  where+    anyAny :: forall a b. S a b x y -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    anyAny s tA tB =+      case tA of+        Bin pA lA rA    -> binAny s (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> Nil++    tipAny+      :: forall a b. S a b x y -> UTip a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    tipAny s uA@(# _, nA, arrA, _, _ #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s uA tA (# pB, lB, rB #)++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s uA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' uB uA tA lenB++        Nil             -> Nil++    tipTip+      :: forall a b. S a b x y -> UTip a -> UTip b -> Radix1Tree b -> Int -> Radix1Tree c+    tipTip s (# wA0, nA, arrA, mA, dA #) (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC | Just xA <- mA, Just xB <- mB = f s xA xB+                                         | otherwise                    = Nothing++                                  in retip arrA' mC (anyAny s dA dB)++                             else retip arrA' Nothing $+                                    let !(# s' #) = other s+                                    in tipAny s' (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise = Nil++    binAny+      :: forall a b. S a b x y -> UBin a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    binAny s uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' (# wB, 0, arrB, mB, dB #) tB uA++        Nil             -> Nil++    tipBin :: forall a b. S a b x y -> UTip a -> Radix1Tree a -> UBin b -> Radix1Tree c+    tipBin s uA@(# wA, _, _, _, _ #) tA (# pB, lB, rB #)+      | beyond pB wA = Nil+      | otherwise    = tipAny s uA tA $ if wA < pB+                                          then lB+                                          else rB++    binBin+      :: forall a b. S a b x y+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree c+    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny s lA lB) (anyAny s rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s+                               in binAny s' uB tB rA+           | pA >= lower pB -> binAny s uA tA lB+           | otherwise      -> Nil++        GT | pA <= upper pB -> binAny s uA tA rB+           | pB >= lower pA -> let !(# s' #) = other s+                               in binAny s' uB tB lA+           | otherwise      -> Nil++++intersectionWithKey0'+  :: (Build -> a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c+intersectionWithKey0' f (RadixTree mA tA) (RadixTree mB tB) =+  let mC | Just a <- mA, Just b <- mB = Just $! f (Build Lin) a b+         | otherwise                  = Nothing++  in RadixTree mC $ intersectionWithKey_+                      ( \s b arr vA vB ->+                           Just $! let b0 = Build $ Snoc b arr+                                   in case s of+                                        L -> f b0 vA vB+                                        R -> f b0 vB vA+                      )+                      tA tB++intersectionWithKey1'+  :: (Build1 -> a -> b -> c) -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+intersectionWithKey1' f =+  intersectionWithKey_ $ \s b arr vA vB ->+    Just $! let b1 = Build1 $ b :/ arr+            in case s of+                 L -> f b1 vA vB+                 R -> f b1 vB vA++{-# INLINE intersectionWithKey_ #-}+intersectionWithKey_+  :: (forall x y. S x y a b -> Tsil ByteArray -> ByteArray -> x -> y -> Maybe c)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree c+intersectionWithKey_+  (f :: forall n o. S n o x y -> Tsil ByteArray -> ByteArray -> n -> o -> Maybe c) =+    anyAny L Lin+  where+    anyAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    anyAny s b tA tB =+      case tA of+        Bin pA lA rA    -> binAny s b (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s b (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> Nil++    tipAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    tipAny s b uA@(# _, nA, arrA, _, _ #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s b uA tA (# pB, lB, rB #)++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s b uA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' b uB uA tA lenB++        Nil             -> Nil++    tipTip+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> UTip b -> Radix1Tree b -> Int -> Radix1Tree c+    tipTip s b (# wA0, nA, arrA, mA, dA #) (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC | Just xA <- mA, Just xB <- mB =+                                             f s b arrA' xA xB++                                         | otherwise                    = Nothing+++                                  in retip arrA' mC (anyAny s (Snoc b arrA') dA dB)++                             else retip arrA' Nothing $+                                    let !(# s' #) = other s+                                    in tipAny s' (Snoc b arrA')+                                         (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | otherwise = Nil++    binAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    binAny s b uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' b (# wB, 0, arrB, mB, dB #) tB uA++        Nil             -> Nil++    tipBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> UBin b -> Radix1Tree c+    tipBin s b uA@(# wA, _, _, _, _ #) tA (# pB, lB, rB #)+      | beyond pB wA = Nil+      | otherwise    = tipAny s b uA tA $ if wA < pB+                                            then lB+                                            else rB++    binBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree c+    binBin s b uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny s b lA lB) (anyAny s b rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s+                               in binAny s' b uB tB rA+           | pA >= lower pB -> binAny s b uA tA lB+           | otherwise      -> Nil++        GT | pA <= upper pB -> binAny s b uA tA rB+           | pB >= lower pA -> let !(# s' #) = other s+                               in binAny s' b uB tB lA+           | otherwise      -> Nil++++{-# INLINE merge0 #-}+merge0+  :: (Build -> a -> b -> Maybe c)+  -> (Build -> a -> Maybe c)+  -> (Build -> Radix1Tree a -> Radix1Tree c)+  -> (Build -> b -> Maybe c)+  -> (Build -> Radix1Tree b -> Radix1Tree c)+  -> RadixTree a+  -> RadixTree b+  -> RadixTree c+merge0 f oneX treeX oneY treeY = \(RadixTree mA tA) (RadixTree mB tB) ->+  let mC = case mA of+             Just xA -> case mB of+                          Just xB -> f (Build Lin) xA xB+                          Nothing -> oneX (Build Lin) xA++             Nothing -> case mB of+                          Just xB -> oneY (Build Lin) xB+                          Nothing -> Nothing++  in RadixTree mC $+       merge_ (\b arr -> f (Build $ Snoc b arr))+         (\b arr -> oneX (Build $ Snoc b arr)) treeX+         (\b arr -> oneY (Build $ Snoc b arr)) treeY+         tA tB++{-# INLINE merge1 #-}+merge1+  :: (Build1 -> a -> b -> Maybe c)+  -> (Build1 -> a -> Maybe c)+  -> (Build -> Radix1Tree a -> Radix1Tree c)+  -> (Build1 -> b -> Maybe c)+  -> (Build -> Radix1Tree b -> Radix1Tree c)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree c+merge1 f oneX treeX oneY treeY =+  merge_ (\b arr -> f (Build1 $ b :/ arr))+    (\b arr -> oneX (Build1 $ b :/ arr)) treeX+    (\b arr -> oneY (Build1 $ b :/ arr)) treeY++{-# INLINE merge_ #-}+merge_+  :: (Tsil ByteArray -> ByteArray -> a -> b -> Maybe c)+  -> (Tsil ByteArray -> ByteArray -> a -> Maybe c)+  -> (Build -> Radix1Tree a -> Radix1Tree c)+  -> (Tsil ByteArray -> ByteArray -> b -> Maybe c)+  -> (Build -> Radix1Tree b -> Radix1Tree c)+  -> Radix1Tree a+  -> Radix1Tree b+  -> Radix1Tree c+merge_ (f :: Tsil ByteArray -> ByteArray -> x -> y -> Maybe c) oneX treeX oneY treeY =+  anyAny L Lin+  where+    sideA :: forall a b. S a b x y -> Tsil ByteArray -> Radix1Tree a -> Radix1Tree c+    sideA s b tA = case s of+                     L -> treeX (Build b) tA+                     R -> treeY (Build b) tA++    sideB :: forall a b. S a b x y -> Tsil ByteArray -> Radix1Tree b -> Radix1Tree c+    sideB s b tB = case s of+                     L -> treeY (Build b) tB+                     R -> treeX (Build b) tB++    anyAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    anyAny s b tA tB =+      case tA of+        Bin pA lA rA    -> binAny s b (# pA, lA, rA #) tA tB++        Tip arrA mA dA  -> let !wA = indexByteArray arrA 0+                           in tipAny s b (# wA, 0, arrA, mA, dA #) tA tB++        Nil             -> sideB s b tB++    tipAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    tipAny s b uA@(# _, nA, arrA, mA, dA #) tA tB =+      case tB of+        Bin pB lB rB    -> tipBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !wB = indexByteArray arrB 0++                               uB = (# wB, 0, arrB, mB, dB #)++                               !lenA = sizeofByteArray arrA - nA++                               !lenB = sizeofByteArray arrB++                           in if lenB > lenA+                                then tipTip s b uA tA uB tB lenA++                                else let !(# s' #) = other s+                                     in tipTip s' b uB tB uA tA lenB++        Nil             -> sideA s b $ if nA == 0+                                         then tA+                                         else Tip (dropByteArray nA arrA) mA dA++    tipTip+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> UTip b -> Radix1Tree b -> Int -> Radix1Tree c+    tipTip s b (# wA0, nA, arrA, mA, dA #) tA (# wB0, nB, arrB, mB, dB #) tB len =+      go wA0 wB0 1+      where+        go wA wB !o+          | wA == wB  =+              let !nB' = nB + o+                  !wB' = indexByteArray arrB nB'++              in if o >= len+                   then let !arrA' | nA == 0   = arrA+                                   | otherwise = dropByteArray nA arrA++                        in if nB' == sizeofByteArray arrB+                             then let mC = case mA of+                                             Just xA ->+                                               case mB of+                                                 Just xB -> case s of+                                                              L -> f b arrA' xA xB+                                                              R -> f b arrA' xB xA++                                                 Nothing -> case s of+                                                              L -> oneX b arrA' xA+                                                              R -> oneY b arrA' xA++                                             Nothing ->+                                               case mB of+                                                 Just xB -> case s of+                                                              L -> oneY b arrA' xB+                                                              R -> oneX b arrA' xB++                                                 Nothing -> Nothing++                                  in retip arrA' mC (anyAny s (Snoc b arrA') dA dB)++                             else let mC = case mA of+                                             Just xA -> case s of+                                                          L -> oneX b arrA' xA+                                                          R -> oneY b arrA' xA++                                             Nothing -> Nothing++                                  in retip arrA' mC $+                                       let !(# s' #) = other s+                                       in tipAny s' (Snoc b arrA')+                                            (# wB', nB', arrB, mB, dB #) tB dA++                   else let !nA' = nA + o+                            !wA' = indexByteArray arrA nA'++                        in go wA' wB' (o + 1)++          | o == 1 =+              safeJoin wA ( sideA s b $ if nA == 0+                                          then tA+                                          else Tip (dropByteArray nA arrA) mA dA+                          )+                       wB ( sideB s b $ if nB == 0+                                          then tB+                                          else Tip (dropByteArray nB arrB) mB dB+                          )++          | otherwise =+              let !o' = o - 1++                  !(# !arrC, !arrA' #) = splitByteArray nA o' arrA++                  !arrB' = dropByteArray (nB + o') arrB++              in retip arrC Nothing $ safeJoin wA (sideA s b $ Tip arrA' mA dA)+                                               wB (sideB s b $ Tip arrB' mB dB)++    binAny+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> Radix1Tree b -> Radix1Tree c+    binAny s b uA tA tB =+      case tB of+        Bin pB lB rB    -> binBin s b uA tA (# pB, lB, rB #) tB++        Tip arrB mB dB  -> let !(# s' #) = other s++                               !wB = indexByteArray arrB 0++                           in tipBin s' b (# wB, 0, arrB, mB, dB #) tB uA tA++        Nil             -> sideA s b tA++    tipBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UTip a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree c+    tipBin s b uA@(# wA, nA, arrA, mA, dA #) tA (# pB, lB, rB #) tB+      | beyond pB wA = safeJoin wA (sideA s b $ if nA == 0+                                                  then tA+                                                  else Tip (dropByteArray nA arrA) mA dA+                                   )+                                pB (sideB s b tB)++      | wA < pB      = rebin pB (tipAny s b uA tA lB) (sideB s b rB)++      | otherwise    = rebin pB (sideB s b lB) (tipAny s b uA tA rB)++    binBin+      :: forall a b. S a b x y -> Tsil ByteArray+      -> UBin a -> Radix1Tree a -> UBin b -> Radix1Tree b -> Radix1Tree c+    binBin s b uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      let {-# NOINLINE no #-}+          no = safeJoin pA (sideA s b tA) pB (sideB s b tB)++      in case Prelude.compare pA pB of+           EQ                  -> rebin pA (anyAny s b lA lB) (anyAny s b rA rB)++           LT | pB <= upper pA -> let !(# s' #) = other s++                                  in rebin pA (sideA s b lA) (binAny s' b uB tB rA)++              | pA >= lower pB -> rebin pB (binAny s b uA tA lB) (sideB s b rB)++              | otherwise      -> no++           GT | pA <= upper pB -> rebin pB (sideB s b lB) (binAny s b uA tA rB)++              | pB >= lower pA -> let !(# s' #) = other s++                                  in rebin pA (binAny s' b uB tB lA) (sideA s b rA)++              | otherwise      -> no++++{-# INLINE insert0 #-}+insert0 :: Feed -> a -> RadixTree a -> RadixTree a+insert0 (Feed feed) a = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ insert_ a step w z t+      Done     -> RadixTree (Just a) t++{-# INLINE insert1 #-}+insert1 :: Feed1 -> a -> Radix1Tree a -> Radix1Tree a+insert1 (Feed1 w feed) a =+  feed $ \step -> insert_ a step w++{-# INLINE insert_ #-}+insert_ :: a -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+insert_ a step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> join+                            w (singleton_ step w s a)+                            p t++          | w < p      -> Bin p (go w s l) r+          | otherwise  -> Bin p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> Tip arr mx (go u z' dx)+                           Done      -> Tip arr (Just a) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      ->+                             let !(# !brr, !crr #) = splitByteArray 0 (n + 1) arr+                             in Tip brr (Just a) (Tip crr mx dx)++              | n == 0    =+                  join+                    (indexByteArray arr 0) t+                    w (singleton_ step w s a)++              | otherwise =+                  let !(# !brr, !crr #) = splitByteArray 0 n arr+                  in Tip brr Nothing $+                       join+                         (indexByteArray crr 0) (Tip crr mx dx)+                         v (singleton_ step v z a)++        Nil -> singleton_ step w s a++++{-# INLINE insertWith0 #-}+insertWith0 :: (a -> a) -> Feed -> a -> RadixTree a -> RadixTree a+insertWith0 f (Feed feed) a = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ insertWith_ f a step w z t+      Done     ->+        let y = case mx of+                  Just x  -> f x+                  Nothing -> a++        in RadixTree (Just y) t++{-# INLINE insertWith1 #-}+insertWith1 :: (a -> a) -> Feed1 -> a -> Radix1Tree a -> Radix1Tree a+insertWith1 f (Feed1 w feed) a =+  feed $ \step -> insertWith_ f a step w++{-# INLINE insertWith_ #-}+insertWith_+  :: (a -> a) -> a -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+insertWith_ f a step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> join+                            w (singleton_ step w s a)+                            p t++          | w < p      -> Bin p (go w s l) r+          | otherwise  -> Bin p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> Tip arr mx (go u z' dx)+                           Done      -> let y = case mx of+                                                  Just x  -> f x+                                                  Nothing -> a++                                        in Tip arr (Just y) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      ->+                             let !(# !brr, !crr #) = splitByteArray 0 (n + 1) arr+                             in Tip brr (Just a) (Tip crr mx dx)++              | n == 0    =+                  join+                    (indexByteArray arr 0) t+                    w (singleton_ step w s a)++              | otherwise =+                  let !(# !brr, !crr #) = splitByteArray 0 n arr+                  in Tip brr Nothing $+                       join+                         (indexByteArray crr 0) (Tip crr mx dx)+                         v (singleton_ step v z a)++        Nil -> singleton_ step w s a++++{-# INLINE insertWith0' #-}+insertWith0' :: (a -> a) -> Feed -> a -> RadixTree a -> RadixTree a+insertWith0' f (Feed feed) a = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ insertWith'_ f a step w z t+      Done     ->+        let !y = case mx of+                  Just x  -> f x+                  Nothing -> a++        in RadixTree (Just y) t++{-# INLINE insertWith1' #-}+insertWith1' :: (a -> a) -> Feed1 -> a -> Radix1Tree a -> Radix1Tree a+insertWith1' f (Feed1 w feed) a =+  feed $ \step -> insertWith'_ f a step w++{-# INLINE insertWith'_ #-}+insertWith'_+  :: (a -> a) -> a -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+insertWith'_ f a step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> join+                            w (singleton_ step w s $! a)+                            p t++          | w < p      -> Bin p (go w s l) r+          | otherwise  -> Bin p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> Tip arr mx (go u z' dx)+                           Done      -> let !y = case mx of+                                                   Just x  -> f x+                                                   Nothing -> a++                                        in Tip arr (Just y) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      ->+                             let !(# !brr, !crr #) = splitByteArray 0 (n + 1) arr+                             in Tip brr (Just a) (Tip crr mx dx)++              | n == 0    =+                  join+                    (indexByteArray arr 0) t+                    w (singleton_ step w s a)++              | otherwise =+                  let !(# !brr, !crr #) = splitByteArray 0 n arr+                  in Tip brr Nothing $+                       join+                         (indexByteArray crr 0) (Tip crr mx dx)+                         v (singleton_ step v z a)++        Nil -> singleton_ step w s a++++{-# INLINE adjust0 #-}+adjust0 :: (a -> a) -> Feed -> RadixTree a -> RadixTree a+adjust0 f (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ adjust_ f step w z t+      Done     -> RadixTree (fmap f mx) t++{-# INLINE adjust1 #-}+adjust1 :: (a -> a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjust1 f (Feed1 w feed) =+  feed $ \step -> adjust_ f step w++{-# INLINE adjust_ #-}+adjust_ :: (a -> a) -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjust_ f step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> Bin p (go w s l) r+          | otherwise  -> Bin p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> Tip arr mx (go u z' dx)+                           Done      -> Tip arr (fmap f mx) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> t++              | otherwise = t++        Nil -> t++++{-# INLINE adjust0' #-}+adjust0' :: (a -> a) -> Feed -> RadixTree a -> RadixTree a+adjust0' f (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ adjust'_ f step w z t+      Done     -> RadixTree (fmap' f mx) t++{-# INLINE adjust1' #-}+adjust1' :: (a -> a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+adjust1' f (Feed1 w feed) =+  feed $ \step -> adjust'_ f step w++{-# INLINE adjust'_ #-}+adjust'_ :: (a -> a) -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+adjust'_ f step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> Bin p (go w s l) r+          | otherwise  -> Bin p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> Tip arr mx (go u z' dx)+                           Done      -> Tip arr (fmap' f mx) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> t++              | otherwise = t++        Nil -> t++++{-# INLINE delete0 #-}+delete0 :: Feed -> RadixTree a -> RadixTree a+delete0 (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ delete_ step w z t+      Done     -> RadixTree Nothing t++{-# INLINE delete1 #-}+delete1 :: Feed1 -> Radix1Tree a -> Radix1Tree a+delete1 (Feed1 w feed) =+  feed $ \step -> delete_ step w++{-# INLINE delete_ #-}+delete_ :: (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+delete_ step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> rebinL p (go w s l) r+          | otherwise  -> rebinR p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> retip arr mx (go u z' dx)+                           Done      -> retip arr Nothing dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> t++              | otherwise = t++        Nil          -> t++++{-# INLINE prune0 #-}+prune0 :: Openness -> Feed -> RadixTree a -> RadixTree a+prune0 openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ prune_ openness step w z t+      Done     ->+        let my = case openness of+                   Open   -> mx+                   Closed -> Nothing++        in RadixTree my Nil++{-# INLINE prune1 #-}+prune1 :: Openness -> Feed1 -> Radix1Tree a -> Radix1Tree a+prune1 openness (Feed1 w feed) =+  feed $ \step -> prune_ openness step w++{-# INLINE prune_ #-}+prune_ :: Openness -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+prune_ openness step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> rebinL p (go w s l) r+          | otherwise  -> rebinR p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> retip arr mx (go u z' dx)+                           Done      ->+                             case openness of+                               Open   -> retip arr mx Nil+                               Closed -> Nil++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> Nil++              | otherwise = t++        Nil          -> t++++{-# INLINE update0 #-}+update0 :: (a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a+update0 f (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ update_ f step w z t+      Done     -> RadixTree (f =<< mx) t++{-# INLINE update1 #-}+update1 :: (a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+update1 f (Feed1 w feed) =+  feed $ \step -> update_ f step w++{-# INLINE update_ #-}+update_+  :: (a -> Maybe a) -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+update_ f step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> t+          | w < p      -> rebinL p (go w s l) r+          | otherwise  -> rebinR p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> retip arr mx (go u z' dx)+                           Done      -> retip arr (f =<< mx) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      -> t++              | otherwise = t++        Nil         -> t++++{-# INLINE alter0 #-}+alter0 :: (Maybe a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a+alter0 f (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ alter_ f step w z t+      Done     -> RadixTree (f mx) t++{-# INLINE alter1 #-}+alter1 :: (Maybe a -> Maybe a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+alter1 f (Feed1 w feed) =+  feed $ \step -> alter_ f step w++{-# INLINE alter_ #-}+alter_+  :: (Maybe a -> Maybe a)+  -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+alter_ f step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> case f Nothing of+                            Nothing -> t+                            Just a  -> join+                                         w (singleton_ step w s a)+                                         p t++          | w < p      -> rebinL p (go w s l) r+          | otherwise  -> rebinR p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  if n + 1 >= sizeofByteArray arr+                    then case step z of+                           More u z' -> retip arr mx (go u z' dx)+                           Done      -> retip arr (f mx) dx++                    else case step z of+                           More u z' -> goarr u z' (n + 1)+                           Done      ->+                             case f Nothing of+                               Nothing -> t+                               Just a  ->+                                 let !(# !brr, !crr #) = splitByteArray 0 (n + 1) arr+                                 in Tip brr (Just a) (Tip crr mx dx)++              | otherwise =+                  case f Nothing of+                    Nothing -> t+                    Just a  ->+                      if n == 0+                        then join+                               (indexByteArray arr 0) (Tip arr mx dx)+                               w (singleton_ step v z a)++                        else let !(# !brr, !crr #) = splitByteArray 0 n arr+                             in Tip brr Nothing $+                                  join+                                    (indexByteArray crr 0) (Tip crr mx dx)+                                    v (singleton_ step v z a)++        Nil       ->+          case f Nothing of+            Nothing -> t+            Just a  -> singleton_ step w s a++++{-# INLINE shape0 #-}+shape0 :: (RadixTree a -> RadixTree a) -> Feed -> RadixTree a -> RadixTree a+shape0 f (Feed feed) = \t0@(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z -> RadixTree mx $ shape_ f step w z t+      Done     -> f t0++{-# INLINE shape1 #-}+shape1 :: (RadixTree a -> RadixTree a) -> Feed1 -> Radix1Tree a -> Radix1Tree a+shape1 f (Feed1 w feed) =+  feed $ \step -> shape_ f step w++{-# INLINE shape_ #-}+shape_+  :: (RadixTree a -> RadixTree a)+  -> (x -> Step Word8 x) -> Word8 -> x -> Radix1Tree a -> Radix1Tree a+shape_ f step = go+  where+    go w s t =+      case t of+        Bin p l r+          | beyond p w -> let !(RadixTree my dy) = f (RadixTree Nothing Nil)+                          in case retip (fromStep step w s) my dy of+                               Nil -> t+                               dz  -> join+                                        w dz+                                        p t++          | w < p      -> rebinL p (go w s l) r+          | otherwise  -> rebinR p l (go w s r)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n+              | v == indexByteArray arr n =+                  let n' = n + 1+                  in if n' >= sizeofByteArray arr+                       then case step z of+                              More u z' -> retip arr mx (go u z' dx)+                              Done      -> let !(RadixTree my dy) = f (RadixTree mx dx)+                                           in retip arr my dy++                       else case step z of+                              More u z' -> goarr u z' n'+                              Done      ->+                                let !(# !brr, !crr #) = splitByteArray 0 n' arr++                                    !(RadixTree my dy) = f (RadixTree Nothing (Tip crr mx dx))++                                in retip brr my dy++              | otherwise =+                  let !(RadixTree my dy) = f (RadixTree Nothing Nil)+                  in case retip (fromStep step v z) my dy of+                       Nil -> t+                       dz  ->+                         if n == 0+                           then join+                                  (indexByteArray arr 0) (Tip arr mx dx)+                                  v dz++                           else let !(# !brr, !crr #) = splitByteArray 0 n arr+                                in Tip brr Nothing $+                                     join+                                       (indexByteArray crr 0) (Tip crr mx dx)+                                       v dz++        Nil       ->+          let !(RadixTree my dy) = f (RadixTree Nothing Nil)+          in retip (fromStep step w s) my dy++++-- | Result of a tree split.+data Split l r = Split !(RadixTree l) !(RadixTree r)++{-# INLINE splitL0 #-}+splitL0 :: Openness -> Feed -> RadixTree a -> Split a a+splitL0 openness (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+        let !(# !l, !r #) = splitL_ openness step w z t+        in Split (RadixTree mx l) (RadixTree Nothing r)++      Done     ->+        let !(# !my, !mz #) = case openness of+                                Open   -> (# Nothing, mx #)+                                Closed -> (# mx, Nothing #)++        in Split (RadixTree my Nil) (RadixTree mz t)++-- | Result of a tree split.+data Split1 l r = Split1 !(Radix1Tree l) !(Radix1Tree r)++{-# INLINE splitL1 #-}+splitL1 :: Openness -> Feed1 -> Radix1Tree a -> Split1 a a+splitL1 openness (Feed1 w feed) = \t ->+  feed $ \step s ->+    case splitL_ openness step w s t of+      (# !l, !r #) -> Split1 l r++{-# INLINE splitL_ #-}+splitL_+  :: Openness -> (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> (# Radix1Tree a, Radix1Tree a #)+splitL_ openness step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then let !(# !ll, !lr #) = go w s l+                        in (# ll, rebinL p lr r #)++                   else (# Nil, t #)++            else if w <= upper p+                   then let !(# !rl, !rr #) = go w s r+                        in (# rebinR p l rl, rr #)++                   else (# t, Nil #)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' ->+                              let !(# !dl, !dr #) = go u z' dx+                              in (# retip arr mx dl, retip arr Nothing dr #)++                            Done      ->+                              let !(# !my, !mz #) =+                                    case openness of+                                      Open   -> (# Nil             , mx      #)+                                      Closed -> (# retip arr mx Nil, Nothing #)++                              in (# my, retip arr mz dx #)++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> (# Nil, t #)++                   LT -> (# t, Nil #)++                   GT -> (# Nil, t #)++        Nil -> (# Nil, Nil #)++++-- | Result of a tree split with a lookup.+data SplitLookup l x r = SplitLookup !(RadixTree l) !(Maybe x) !(RadixTree r)++{-# INLINE splitLookup0 #-}+splitLookup0 :: Feed -> RadixTree a -> SplitLookup a a a+splitLookup0 (Feed feed) = \(RadixTree mx t) ->+  feed $ \step s ->+    case step s of+      More w z ->+        let !(# !l, !my, !r #) = splitLookup_ step w z t+        in SplitLookup (RadixTree mx l) my (RadixTree Nothing r)++      Done     -> SplitLookup (RadixTree Nothing Nil) mx (RadixTree Nothing t)++-- | Result of a tree split with a lookup.+data SplitLookup1 l x r = SplitLookup1 !(Radix1Tree l) !(Maybe x) !(Radix1Tree r)++{-# INLINE splitLookup1 #-}+splitLookup1 :: Feed1 -> Radix1Tree a -> SplitLookup1 a a a+splitLookup1 (Feed1 w feed) = \t ->+  feed $ \step s ->+    case splitLookup_ step w s t of+      (# !l, !mx, !r #) -> SplitLookup1 l mx r++{-# INLINE splitLookup_ #-}+splitLookup_+  :: (x -> Step Word8 x)+  -> Word8 -> x -> Radix1Tree a -> (# Radix1Tree a, Maybe a, Radix1Tree a #)+splitLookup_ step = go+  where+    go w s t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then let !(# !ll, !my, !lr #) = go w s l+                        in (# ll, my, rebinL p lr r #)++                   else (# Nil, Nothing, t #)++            else if w <= upper p+                   then let !(# !rl, !my, !rr #) = go w s r+                        in (# rebinR p l rl, my, rr #)++                   else (# t, Nothing, Nil #)++        Tip arr mx dx -> goarr w s 0+          where+            goarr v z n =+              let n' = n + 1+              in case indexByteArray arr n `compare` v of+                   EQ | n' >= sizeofByteArray arr ->+                          case step z of+                            More u z' ->+                              let !(# !dl, !my, !dr #) = go u z' dx+                              in (# retip arr mx dl, my, retip arr Nothing dr #)++                            Done      ->+                              (# Nil, mx, retip arr Nothing dx #)++                      | otherwise ->+                          case step z of+                            More u z' -> goarr u z' n'+                            Done      -> (# Nil, Nothing, t #)++                   LT -> (# t, Nothing, Nil #)++                   GT -> (# Nil, Nothing, t #)++        Nil -> (# Nil, Nothing, Nil #)++++{-# INLINE filterMaybe #-}+filterMaybe :: (a -> Bool) -> Maybe a -> Maybe a+filterMaybe f mx =+  case mx of+    Just x | f x -> Just x+    _            -> Nothing++filter0 :: (a -> Bool) -> RadixTree a -> RadixTree a+filter0 f (RadixTree mx t) = RadixTree (filterMaybe f mx) (filter1 f t)++filter1 :: (a -> Bool) -> Radix1Tree a -> Radix1Tree a+filter1 f = go+  where+    go t =+      case t of+        Bin p l r     -> rebin p (go l) (go r)+        Tip arr mx dx -> retip arr (filterMaybe f mx) (go dx)+        Nil           -> Nil++++filterWithKey0 :: (Build -> a -> Bool) -> RadixTree a -> RadixTree a+filterWithKey0 f (RadixTree mx t) =+  RadixTree (filterMaybe (f (Build Lin)) mx) $+    filterWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++filterWithKey1 :: (Build1 -> a -> Bool) -> Radix1Tree a -> Radix1Tree a+filterWithKey1 f = filterWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE filterWithKey_ #-}+filterWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Bool) -> Radix1Tree a -> Radix1Tree a+filterWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> rebin p (go b l) (go b r)++        Tip arr mx dx -> retip arr (filterMaybe (f b arr) mx) (go (Snoc b arr) dx)++        Nil           -> Nil++++mapMaybe0 :: (a -> Maybe b) -> RadixTree a -> RadixTree b+mapMaybe0 f (RadixTree mx t) = RadixTree (f =<< mx) (mapMaybe1 f t)++mapMaybe1 :: (a -> Maybe b) -> Radix1Tree a -> Radix1Tree b+mapMaybe1 f = go+  where+    go t =+      case t of+        Bin p l r     -> rebin p (go l) (go r)+        Tip arr mx dx -> retip arr (f =<< mx) (go dx)+        Nil           -> Nil++++mapMaybeWithKey0 :: (Build -> a -> Maybe b) -> RadixTree a -> RadixTree b+mapMaybeWithKey0 f (RadixTree mx t) =+  RadixTree (f (Build Lin) =<< mx) $+    mapMaybeWithKey_ (\b arr -> f (Build $ Snoc b arr)) Lin t++mapMaybeWithKey1 :: (Build1 -> a -> Maybe b) -> Radix1Tree a -> Radix1Tree b+mapMaybeWithKey1 f = mapMaybeWithKey_ (\b arr -> f (Build1 $ b :/ arr)) Lin++{-# INLINE mapMaybeWithKey_ #-}+mapMaybeWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Maybe b) -> Tsil ByteArray+  -> Radix1Tree a -> Radix1Tree b+mapMaybeWithKey_ f = go+  where+    go b t =+      case t of+        Bin p l r     -> rebin p (go b l) (go b r)++        Tip arr mx dx -> retip arr (f b arr =<< mx) (go (Snoc b arr) dx)++        Nil           -> Nil++++partition0 :: (a -> Bool) -> RadixTree a -> Split a a+partition0 f = \(RadixTree mx t) ->+  let !(# !l, !r #) = partition_ f t++      !(# !my, !mz #) =+        case mx of+          Just x+            | f x       -> (# mx     , Nothing #)+            | otherwise -> (# Nothing, mx      #)++          Nothing       -> (# Nothing, Nothing #)++  in Split (RadixTree my l) (RadixTree mz r)++partition1 :: (a -> Bool) -> Radix1Tree a -> Split1 a a+partition1 f = \t ->+  case partition_ f t of+    (# !l, !r #) -> Split1 l r++partition_ :: (a -> Bool) -> Radix1Tree a -> (# Radix1Tree a, Radix1Tree a #)+partition_ f = go+  where+    go t =+      case t of+        Bin p l r   ->+          let !(# !ly, !lz #) = go l+              !(# !ry, !rz #) = go r++          in (# rebin p ly ry, rebin p lz rz #)++        Tip arr mx dx ->+          let !(# !dy, !dz #) = go dx+          in case mx of+               Nothing -> (# retip arr Nothing dy, retip arr Nothing dz #)+               Just x  ->+                 if f x+                   then (# Tip   arr (Just x) dy, retip arr Nothing  dz #)+                   else (# retip arr Nothing  dy, Tip   arr (Just x) dz #)++        Nil         -> (# Nil, Nil #)++++partitionWithKey0 :: (Build -> a -> Bool) -> RadixTree a -> Split a a+partitionWithKey0 f = \(RadixTree mx t) ->+  let !(# !l, !r #) = partitionWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++      !(# !my, !mz #) =+        case mx of+          Just x+            | f (Build Lin) x -> (# mx     , Nothing #)+            | otherwise       -> (# Nothing, mx      #)++          Nothing             -> (# Nothing, Nothing #)++  in Split (RadixTree my l) (RadixTree mz r)++partitionWithKey1 :: (Build1 -> a -> Bool) -> Radix1Tree a -> Split1 a a+partitionWithKey1 f = \t ->+  case partitionWithKey_ (\b arr -> f (Build1 $ b :/ arr)) t of+    (# !l, !r #) -> Split1 l r++{-# INLINE partitionWithKey_ #-}+partitionWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Bool)+  -> Radix1Tree a -> (# Radix1Tree a, Radix1Tree a #)+partitionWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     ->+          let !(# !ly, !lz #) = go b l+              !(# !ry, !rz #) = go b r++          in (# rebin p ly ry, rebin p lz rz #)++        Tip arr mx dx ->+          let !(# !dy, !dz #) = go (Snoc b arr) dx+          in case mx of+               Nothing -> (# retip arr Nothing dy, retip arr Nothing dz #)+               Just x  ->+                 if f b arr x+                   then (# Tip   arr (Just x) dy, retip arr Nothing  dz #)+                   else (# retip arr Nothing  dy, Tip   arr (Just x) dz #)++        Nil         -> (# Nil, Nil #)++++mapEither0 :: (a -> Either b c) -> RadixTree a -> Split b c+mapEither0 f = \(RadixTree mx t) ->+  let !(# !l, !r #) = mapEither_ f t++      !(# !my, !mz #) =+        case mx of+          Just x ->+            case f x of+              Left y  -> (# Just y , Nothing #)+              Right z -> (# Nothing, Just z  #)++          Nothing     -> (# Nothing, Nothing #)++  in Split (RadixTree my l) (RadixTree mz r)++mapEither1 :: (a -> Either b c) -> Radix1Tree a -> Split1 b c+mapEither1 f = \t ->+  case mapEither_ f t of+    (# !l, !r #) -> Split1 l r++mapEither_ :: (a -> Either b c) -> Radix1Tree a -> (# Radix1Tree b, Radix1Tree c #)+mapEither_ f = go+  where+    go t =+      case t of+        Bin p l r     ->+          let !(# !ly, !lz #) = go l+              !(# !ry, !rz #) = go r++          in (# rebin p ly ry, rebin p lz rz #)++        Tip arr mx dx ->+          let !(# !dy, !dz #) = go dx+          in case mx of+               Nothing -> (# retip arr Nothing dy, retip arr Nothing dz #)+               Just x  ->+                 case f x of+                   Left y  -> (# Tip   arr (Just y) dy, retip arr Nothing  dz #)+                   Right z -> (# retip arr Nothing  dy, Tip   arr (Just z) dz #)++        Nil         -> (# Nil, Nil #)++++mapEitherWithKey0 :: (Build -> a -> Either b c) -> RadixTree a -> Split b c+mapEitherWithKey0 f = \(RadixTree mx t) ->+  let !(# !l, !r #) = mapEitherWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++      !(# !my, !mz #) =+        case mx of+          Just x ->+            case f (Build Lin) x of+              Left y  -> (# Just y , Nothing #)+              Right z -> (# Nothing, Just z  #)++          Nothing     -> (# Nothing, Nothing #)++  in Split (RadixTree my l) (RadixTree mz r)++mapEitherWithKey1 :: (Build1 -> a -> Either b c) -> Radix1Tree a -> Split1 b c+mapEitherWithKey1 f = \t ->+  case mapEitherWithKey_ (\b arr -> f (Build1 $ b :/ arr)) t of+    (# !l, !r #) -> Split1 l r++{-# INLINE mapEitherWithKey_ #-}+mapEitherWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Either b c)+  -> Radix1Tree a -> (# Radix1Tree b, Radix1Tree c #)+mapEitherWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     ->+          let !(# !ly, !lz #) = go b l+              !(# !ry, !rz #) = go b r++          in (# rebin p ly ry, rebin p lz rz #)++        Tip arr mx dx ->+          let !(# !dy, !dz #) = go (Snoc b arr) dx+          in case mx of+               Nothing -> (# retip arr Nothing dy, retip arr Nothing dz #)+               Just x  ->+                 case f b arr x of+                   Left y  -> (# Tip   arr (Just y) dy, retip arr Nothing  dz #)+                   Right z -> (# retip arr Nothing  dy, Tip   arr (Just z) dz #)++        Nil         -> (# Nil, Nil #)++++moduleLoc1 :: String+moduleLoc1 = "Radix1Tree.Word8.Strict"++++lookupMin0 :: RadixTree a -> Maybe a+lookupMin0 (RadixTree mx t) =+  case mx of+    Just x  -> Just x+    Nothing -> lookupMin1 t++lookupMin1 :: Radix1Tree a -> Maybe a+lookupMin1 Nil = Nothing+lookupMin1 t   = let !(# a #) = unsafeLookupMin1 t+                 in Just a++unsafeLookupMin1 :: Radix1Tree a -> (# a #)+unsafeLookupMin1 t =+  case t of+    Bin _ l _   -> unsafeLookupMin1 l+    Tip _ mx dx -> case mx of+                     Just x  -> (# x #)+                     Nothing -> unsafeLookupMin1 dx++    Nil         -> throw $ MalformedTree moduleLoc1 "lookupMin"++++lookupMinWithKey0 :: RadixTree a -> Maybe (Lookup a)+lookupMinWithKey0 (RadixTree mx t) =+  case mx of+    Just x  -> Just (Lookup (Build Lin) x)+    Nothing ->+      case t of+        Nil -> Nothing+        _   -> let !(# b, arr, a #) = unsafeLookupMinWithKey_ Lin t+               in Just $! Lookup (Build $ Snoc b arr) a++lookupMinWithKey1 :: Radix1Tree a -> Maybe (Lookup1 a)+lookupMinWithKey1 Nil = Nothing+lookupMinWithKey1 t   = Just $! unsafeLookupMinWithKey1 t++unsafeLookupMinWithKey1 :: Radix1Tree a -> Lookup1 a+unsafeLookupMinWithKey1 t =+  let !(# b, arr, a #) = unsafeLookupMinWithKey_ Lin t+  in Lookup1 (Build1 $ b :/ arr) a++unsafeLookupMinWithKey_+  :: Tsil ByteArray -> Radix1Tree a -> (# Tsil ByteArray, ByteArray, a #)+unsafeLookupMinWithKey_ = go+  where+    go b t =+      case t of+        Bin _ l _     -> go b l+        Tip arr mx dx -> case mx of+                           Just x  -> (# b, arr, x #)+                           Nothing -> go (Snoc b arr) dx++        Nil           -> throw $ MalformedTree moduleLoc1 "lookupMinWithKey"++++lookupMax0 :: RadixTree a -> Maybe a+lookupMax0 (RadixTree mx t) =+  case t of+    Nil -> mx+    _   -> let !(# a #) = unsafeLookupMax1 t+           in Just a++lookupMax1 :: Radix1Tree a -> Maybe a+lookupMax1 Nil = Nothing+lookupMax1 t   = let !(# a #) = unsafeLookupMax1 t+                 in Just a++unsafeLookupMax1 :: Radix1Tree a -> (# a #)+unsafeLookupMax1 t =+  case t of+    Bin _ _ r   -> unsafeLookupMax1 r+    Tip _ mx dx -> case dx of+                     Nil | Just x <- mx -> (# x #)+                     _                  -> unsafeLookupMax1 dx++    Nil         -> throw $ MalformedTree moduleLoc1 "lookupMin"++++lookupMaxWithKey0 :: RadixTree a -> Maybe (Lookup a)+lookupMaxWithKey0 (RadixTree mx t) =+  case t of+    Nil -> Lookup (Build Lin) `fmap'` mx+    _   -> let !(# b, arr, a #) = unsafeLookupMaxWithKey_ Lin t+           in Just $! Lookup (Build $ Snoc b arr) a++lookupMaxWithKey1 :: Radix1Tree a -> Maybe (Lookup1 a)+lookupMaxWithKey1 Nil = Nothing+lookupMaxWithKey1 t   = Just $! unsafeLookupMaxWithKey1 t++unsafeLookupMaxWithKey1 :: Radix1Tree a -> Lookup1 a+unsafeLookupMaxWithKey1 t =+  let !(# b, arr, a #) = unsafeLookupMaxWithKey_ Lin t+  in Lookup1 (Build1 $ b :/ arr) a++unsafeLookupMaxWithKey_+  :: Tsil ByteArray -> Radix1Tree a -> (# Tsil ByteArray, ByteArray, a #)+unsafeLookupMaxWithKey_ = go+  where+    go b t =+      case t of+        Bin _ _ r     -> go b r+        Tip arr mx dx -> case dx of+                           Nil | Just x <- mx -> (# b, arr, x #)+                           _                  -> go (Snoc b arr) dx++        Nil           -> throw $ MalformedTree moduleLoc1 "lookupMaxWithKey"++++deleteMin0 :: RadixTree a -> RadixTree a+deleteMin0 (RadixTree mx t) =+  case mx of+    Just _  -> RadixTree Nothing t+    Nothing -> RadixTree mx (deleteMin1 t)++deleteMin1 :: Radix1Tree a -> Radix1Tree a+deleteMin1 Nil = Nil+deleteMin1 r   = unsafeDeleteMin1 r++unsafeDeleteMin1 :: Radix1Tree a -> Radix1Tree a+unsafeDeleteMin1 = go+  where+    go t =+      case t of+        Bin p l r     -> rebinL p (go l) r++        Tip arr mx dx -> case mx of+                           Nothing -> retip arr mx (go dx)+                           Just _  -> retip arr Nothing dx++        Nil           -> Nil++++deleteMax0 :: RadixTree a -> RadixTree a+deleteMax0 t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just _  -> RadixTree Nothing t+             Nothing -> t0++    _   -> RadixTree mx (unsafeDeleteMax1 t)++deleteMax1 :: Radix1Tree a -> Radix1Tree a+deleteMax1 Nil = Nil+deleteMax1 r   = unsafeDeleteMax1 r++unsafeDeleteMax1 :: Radix1Tree a -> Radix1Tree a+unsafeDeleteMax1 = go+  where+    go t =+      case t of+        Bin p l r     -> rebinR p l (go r)++        Tip arr mx dx -> case dx of+                           Nil     -> Nil+                           _       -> retip arr mx (go dx)++        Nil           -> Nil++++adjustMin0 :: (a -> a) -> RadixTree a -> RadixTree a+adjustMin0 f (RadixTree mx t) =+  case mx of+    Just x  -> RadixTree (Just $ f x) t+    Nothing -> RadixTree mx (adjustMin1 f t)++adjustMin1 :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMin1 _ Nil = Nil+adjustMin1 f r   = unsafeAdjustMin1 f r++unsafeAdjustMin1 :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMin1 f = go+  where+    go t =+      case t of+        Bin p l r     -> Bin p (go l) r++        Tip arr mx dx -> case mx of+                           Just x  -> Tip arr (Just $ f x) dx+                           Nothing -> Tip arr mx (go dx)++        Nil           -> Nil++++adjustMin0' :: (a -> a) -> RadixTree a -> RadixTree a+adjustMin0' f (RadixTree mx t) =+  case mx of+    Just x  -> RadixTree (Just $! f x) t+    Nothing -> RadixTree mx (adjustMin1' f t)++adjustMin1' :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMin1' _ Nil = Nil+adjustMin1' f r   = unsafeAdjustMin1' f r++unsafeAdjustMin1' :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMin1' f = go+  where+    go t =+      case t of+        Bin p l r     -> Bin p (go l) r++        Tip arr mx dx -> case mx of+                           Just x  -> Tip arr (Just $! f x) dx+                           Nothing -> Tip arr mx (go dx)++        Nil           -> Nil++++adjustMinWithKey0 :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMinWithKey0 f (RadixTree mx t) =+  case mx of+    Just x  -> RadixTree (Just $ f (Build Lin) x) t+    Nothing -> RadixTree mx $+                 case t of+                   Nil -> Nil+                   _   -> unsafeAdjustMinWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++adjustMinWithKey1 :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMinWithKey1 _ Nil = Nil+adjustMinWithKey1 f r   = unsafeAdjustMinWithKey1 f r++unsafeAdjustMinWithKey1 :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMinWithKey1 f = unsafeAdjustMinWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE unsafeAdjustMinWithKey_ #-}+unsafeAdjustMinWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMinWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> Bin p (go b l) r++        Tip arr mx dx -> case mx of+                           Just x  -> Tip arr (Just $ f b arr x) dx+                           Nothing -> Tip arr mx (go (Snoc b arr) dx)++        Nil           -> Nil++++adjustMinWithKey0' :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMinWithKey0' f (RadixTree mx t) =+  case mx of+    Just x  -> RadixTree (Just $! f (Build Lin) x) t+    Nothing -> RadixTree mx $+                 case t of+                   Nil -> Nil+                   _   -> unsafeAdjustMinWithKey'_ (\b arr -> f (Build $ Snoc b arr)) t++adjustMinWithKey1' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMinWithKey1' _ Nil = Nil+adjustMinWithKey1' f r   = unsafeAdjustMinWithKey1' f r++unsafeAdjustMinWithKey1' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMinWithKey1' f = unsafeAdjustMinWithKey'_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE unsafeAdjustMinWithKey'_ #-}+unsafeAdjustMinWithKey'_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMinWithKey'_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> Bin p (go b l) r++        Tip arr mx dx -> case mx of+                           Just x  -> Tip arr (Just $! f b arr x) dx+                           Nothing -> Tip arr mx (go (Snoc b arr) dx)++        Nil           -> Nil++++adjustMax0 :: (a -> a) -> RadixTree a -> RadixTree a+adjustMax0 f t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just x  -> RadixTree (Just $ f x) t+             Nothing -> t0++    _   -> RadixTree mx (unsafeAdjustMax1 f t)++adjustMax1 :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMax1 _ Nil = Nil+adjustMax1 f r   = unsafeAdjustMax1 f r++unsafeAdjustMax1 :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMax1 f = go+  where+    go t =+      case t of+        Bin p l r     -> Bin p l (go r)++        Tip arr mx dx -> case dx of+                           Nil | Just x <- mx -> Tip arr (Just $ f x) dx+                           _                  -> Tip arr mx (go dx)++        Nil           -> Nil++++adjustMax0' :: (a -> a) -> RadixTree a -> RadixTree a+adjustMax0' f t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just x  -> RadixTree (Just $! f x) t+             Nothing -> t0++    _   -> RadixTree mx (unsafeAdjustMax1 f t)++adjustMax1' :: (a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMax1' _ Nil = Nil+adjustMax1' f r   = unsafeAdjustMax1' f r++unsafeAdjustMax1' :: (a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMax1' f = go+  where+    go t =+      case t of+        Bin p l r     -> Bin p l (go r)++        Tip arr mx dx -> case dx of+                           Nil | Just x <- mx -> Tip arr (Just $! f x) dx+                           _                  -> Tip arr mx (go dx)++        Nil           -> Nil++++adjustMaxWithKey0 :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMaxWithKey0 f t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just x  -> RadixTree (Just $ f (Build Lin) x) t+             Nothing -> t0++    _   -> RadixTree mx $+             unsafeAdjustMaxWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++adjustMaxWithKey1 :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMaxWithKey1 _ Nil = Nil+adjustMaxWithKey1 f r   = unsafeAdjustMaxWithKey1 f r++unsafeAdjustMaxWithKey1 :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMaxWithKey1 f = unsafeAdjustMaxWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE unsafeAdjustMaxWithKey_ #-}+unsafeAdjustMaxWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMaxWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> Bin p l (go b r)++        Tip arr mx dx ->+          case dx of+            Nil | Just x <- mx -> Tip arr (Just $ f b arr x) dx+            _                  -> Tip arr mx (go (Snoc b arr) dx)++        Nil           -> Nil++++adjustMaxWithKey0' :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMaxWithKey0' f t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just x  -> RadixTree (Just $! f (Build Lin) x) t+             Nothing -> t0++    _   -> RadixTree mx $+             unsafeAdjustMaxWithKey'_ (\b arr -> f (Build $ Snoc b arr)) t++adjustMaxWithKey1' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+adjustMaxWithKey1' _ Nil = Nil+adjustMaxWithKey1' f r   = unsafeAdjustMaxWithKey1' f r++unsafeAdjustMaxWithKey1' :: (Build1 -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMaxWithKey1' f = unsafeAdjustMaxWithKey'_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE unsafeAdjustMaxWithKey'_ #-}+unsafeAdjustMaxWithKey'_+  :: (Tsil ByteArray -> ByteArray -> a -> a) -> Radix1Tree a -> Radix1Tree a+unsafeAdjustMaxWithKey'_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> Bin p l (go b r)++        Tip arr mx dx ->+          case dx of+            Nil | Just x <- mx -> Tip arr (Just $! f b arr x) dx+            _                  -> Tip arr mx (go (Snoc b arr) dx)++        Nil           -> Nil++++updateMin0 :: (a -> Maybe a) -> RadixTree a -> RadixTree a+updateMin0 f (RadixTree mx t) =+  case mx of+    Just x  -> RadixTree (f x) t+    Nothing -> RadixTree mx (updateMin1 f t)++updateMin1 :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMin1 _ Nil = Nil+updateMin1 f r   = unsafeUpdateMin1 f r++unsafeUpdateMin1 :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMin1 f = go+  where+    go t =+      case t of+        Bin p l r     -> rebinL p (go l) r++        Tip arr mx dx -> case mx of+                           Just x  -> retip arr (f x) dx+                           Nothing -> retip arr mx (go dx)++        Nil           -> Nil++++updateMinWithKey0 :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a+updateMinWithKey0 f (RadixTree mx t) =+  case mx of+    Just x  -> RadixTree (f (Build Lin) x) t+    Nothing -> RadixTree mx $+                 case t of+                   Nil -> Nil+                   _   -> unsafeUpdateMinWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++updateMinWithKey1 :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMinWithKey1 _ Nil = Nil+updateMinWithKey1 f r   = unsafeUpdateMinWithKey1 f r++unsafeUpdateMinWithKey1 :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMinWithKey1 f = unsafeUpdateMinWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE unsafeUpdateMinWithKey_ #-}+unsafeUpdateMinWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMinWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> rebinL p (go b l) r++        Tip arr mx dx -> case mx of+                           Just x  -> retip arr (f b arr x) dx+                           Nothing -> retip arr mx (go (Snoc b arr) dx)++        Nil           -> Nil++++updateMax0 :: (a -> Maybe a) -> RadixTree a -> RadixTree a+updateMax0 f t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just x  -> RadixTree (f x) t+             Nothing -> t0++    _   -> RadixTree mx (unsafeUpdateMax1 f t)++updateMax1 :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMax1 _ Nil = Nil+updateMax1 f r   = unsafeUpdateMax1 f r++unsafeUpdateMax1 :: (a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMax1 f = go+  where+    go t =+      case t of+        Bin p l r     -> rebinR p l (go r)++        Tip arr mx dx -> case dx of+                           Nil | Just x <- mx -> retip arr (f x) dx+                           _                  -> retip arr mx (go dx)++        Nil           -> Nil++++updateMaxWithKey0 :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a+updateMaxWithKey0 f t0@(RadixTree mx t) =+  case t of+    Nil -> case mx of+             Just x  -> RadixTree (f (Build Lin) x) t+             Nothing -> t0++    _   -> RadixTree mx $+             unsafeUpdateMaxWithKey_ (\b arr -> f (Build $ Snoc b arr)) t++updateMaxWithKey1 :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+updateMaxWithKey1 _ Nil = Nil+updateMaxWithKey1 f r   = unsafeUpdateMaxWithKey1 f r++unsafeUpdateMaxWithKey1 :: (Build1 -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMaxWithKey1 f = unsafeUpdateMaxWithKey_ (\b arr -> f (Build1 $ b :/ arr))++{-# INLINE unsafeUpdateMaxWithKey_ #-}+unsafeUpdateMaxWithKey_+  :: (Tsil ByteArray -> ByteArray -> a -> Maybe a) -> Radix1Tree a -> Radix1Tree a+unsafeUpdateMaxWithKey_ f = go Lin+  where+    go b t =+      case t of+        Bin p l r     -> rebinR p l (go b r)++        Tip arr mx dx -> case dx of+                           Nil | Just x <- mx -> retip arr (f b arr x) dx+                           _                  -> retip arr mx (go (Snoc b arr) dx)++        Nil           -> Nil++++-- | The leftmost value with its key and the rest of the tree.+data ViewL a = ViewL !Build a !(RadixTree a)+               deriving Show++minView0 :: RadixTree a -> Maybe (ViewL a)+minView0 (RadixTree mx t) =+  case mx of+    Just x  -> Just $! ViewL (Build Lin) x (RadixTree Nothing t)+    Nothing ->+      case t of+        Nil -> Nothing+        _   -> Just $! let !(# !b, !arr, x, !t' #) = unsafeMinView_ t+                       in ViewL (Build $ Snoc b arr) x (RadixTree mx t')+++-- | The leftmost value with its key and the rest of the tree.+data ViewL1 a = ViewL1 !Build1 a !(Radix1Tree a)+                deriving Show++minView1 :: Radix1Tree a -> Maybe (ViewL1 a)+minView1 Nil = Nothing+minView1 t   = Just $! unsafeMinView1 t++unsafeMinView1 :: Radix1Tree a -> ViewL1 a+unsafeMinView1 t =+  let !(# !b, !arr, x, !t' #) = unsafeMinView_ t+  in ViewL1 (Build1 $ b :/ arr) x t'++unsafeMinView_ :: Radix1Tree a -> (# Tsil ByteArray, ByteArray, a, Radix1Tree a #)+unsafeMinView_ = go Lin+  where+    go b t =+      case t of+        Bin p l r     ->+          let !(# !b', !brr, z, !l' #) = go b l+          in (# b', brr, z, rebinL p l' r #)++        Tip arr mx dx ->+          case mx of+            Just x  -> (# b, arr, x, retip arr Nothing dx #)+            Nothing ->+              let !(# !b', !brr, z, !dy #) = go (Snoc b arr) dx+              in (# b', brr, z, retip arr mx dy #)++        Nil           -> throw $ MalformedTree moduleLoc1 "minView"++++-- | The rightmost value with its key and the rest of the tree.+data ViewR a = ViewR !(RadixTree a) !Build a+               deriving Show++maxView0 :: RadixTree a -> Maybe (ViewR a)+maxView0 (RadixTree mx t) =+  case t of+    Nil -> ViewR (RadixTree Nothing t) (Build Lin) `fmap'` mx+    _   -> Just $! let !(# !t', !b, !arr, x #) = unsafeMaxView_ t+                   in ViewR (RadixTree mx t') (Build $ Snoc b arr) x+++-- | The rightmost value with its key and the rest of the tree.+data ViewR1 a = ViewR1 !(Radix1Tree a) !Build1 a+                deriving Show++maxView1 :: Radix1Tree a -> Maybe (ViewR1 a)+maxView1 Nil = Nothing+maxView1 t   = Just $! unsafeMaxView1 t++unsafeMaxView1 :: Radix1Tree a -> ViewR1 a+unsafeMaxView1 t =+  let !(# !t', !b, !arr, x #) = unsafeMaxView_ t+  in ViewR1 t' (Build1 $ b :/ arr) x++unsafeMaxView_ :: Radix1Tree a -> (# Radix1Tree a, Tsil ByteArray, ByteArray, a #)+unsafeMaxView_ = go Lin+  where+    go b t =+      case t of+        Bin p l r     ->+          let !(# !r', !b', !brr, z #) = go b r+          in (# rebinR p l r', b', brr, z #)++        Tip arr mx dx ->+          case dx of+            Nil | Just x <- mx -> (# retip arr Nothing dx, b, arr, x #)+            _                  ->+              let !(# !dy, !b', !brr, z #) = go (Snoc b arr) dx+              in (# retip arr mx dy, b', brr, z #)++        Nil           -> throw $ MalformedTree moduleLoc1 "maxView"
+ src/Data/RadixNTree/Word8/Strict/Debug.hs view
@@ -0,0 +1,109 @@+module Data.RadixNTree.Word8.Strict.Debug+  ( showsTree0+  , showsTree1++  , Validity (..)+  , Reason (..)+  , validate0+  , validate1+  ) where++import           Data.ByteArray.NonEmpty+import           Data.RadixNTree.Word8.Debug+import           Data.RadixNTree.Word8.Key+import           Data.RadixNTree.Word8.Strict+import           Numeric.Long+import           Radix.Word8.Debug++import           Data.List.NonEmpty (NonEmpty (..))+import           Data.Primitive.ByteArray++++showsTree0 :: (a -> ShowS) -> RadixTree a -> ShowS+showsTree0 f (RadixTree mx t) =+  showString "RadixTree" . case mx of+                             Just x  -> showString " => " . f x+                             Nothing -> id++                         . showChar '\n'++                         . showsTree_ 2 f t++showsTree1 :: (a -> ShowS) -> Radix1Tree a -> ShowS+showsTree1 f = showsTree_ 0 f++showsTree_ :: Int -> (a -> ShowS) -> Radix1Tree a -> ShowS+showsTree_ n0 f = go n0+  where+    go i t =+      mappend (replicate i ' ') .+        case t of+          Bin p l r   ->+            showString "Bin " . showPrefix p . showChar '\n'+                              . go (i + 2) l . showChar '\n'+                              . go (i + 2) r++          Tip arr mx dx ->+            showString "Tip " . if sizeofByteArray arr <= 0+                                  then id+                                  else let w0 :| ws = toNonEmpty arr+                                       in showLongBin w0+                                            . showString " (" . showLongHex w0 . showChar ')'+                                            . foldr (\x s -> showChar ' ' . showLongHex x . s) id ws++                                 . case mx of+                                     Just x  -> showString " => " . f x+                                     Nothing -> id++                                 . showChar '\n'++                                 . go (i + 2) dx++          Nil           -> showString "Nil"++++validate0 :: RadixTree a -> Validity+validate0 (RadixTree _ t) = validate1 t++validate1 :: Radix1Tree a -> Validity+validate1 = go Lin+  where+    go b t =+      case t of+        Bin p l r+          | p == 0                 -> Invalid (Build b) ZeroPrefix+          | otherwise              ->+              case goBin L b p l of+                Valid -> goBin R b p r+                err   -> err++        Tip arr mx dx+          | sizeofByteArray arr <= 0       -> Invalid (Build b) EmptyByteArray+          | Nothing <- mx, Tip _ _ _ <- dx -> Invalid (Build b) UncompressedTip+          | Nothing <- mx, Nil       <- dx -> Invalid (Build b) UncompressedTip+          | otherwise                      -> go (Snoc b arr) dx++        Nil -> Valid++    goBin s b q x =+      case x of+        Bin p l r+          | p == 0                 -> Invalid (Build b) ZeroPrefix+          | not $ validBelow q s p -> Invalid (Build b) $ PrefixBelow q p+          | otherwise              ->+              case goBin L b p l of+                Valid -> goBin R b p r+                err   -> err++        Tip arr mx dx+          | sizeofByteArray arr <= 0                    -> Invalid (Build b) EmptyByteArray+          | not $ validBelow q s (indexByteArray arr 0) ->+              Invalid (Build b) $ KeyBelow q (indexByteArray arr 0)++          | Nothing <- mx, Tip _ _ _ <- dx     -> Invalid (Build b) UncompressedTip+          | Nothing <- mx, Nil       <- dx     -> Invalid (Build b) UncompressedTip+          | otherwise                          -> go (Snoc b arr) dx++        Nil -> Invalid (Build b) $ MalformedBin q
+ src/Data/RadixNTree/Word8/Strict/TH.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE TemplateHaskellQuotes #-}++module Data.RadixNTree.Word8.Strict.TH+  ( RadixTree+  , sequenceCode0++  , Radix1Tree+  , sequenceCode1+  ) where++import           Data.RadixNTree.Word8.Strict++import           Language.Haskell.TH.Syntax++++sequenceCode0 :: Quote m => RadixTree (Code m a) -> Code m (RadixTree a)+sequenceCode0 (RadixTree mx t) =+  [|| RadixTree $$(sequenceMaybe mx) $$(sequenceCode1 t) ||]++sequenceCode1 :: Quote m => Radix1Tree (Code m a) -> Code m (Radix1Tree a)+sequenceCode1 t =+  case t of+    Bin p l r     ->+      [|| Bin+            p+            $$(sequenceCode1 l)+            $$(sequenceCode1 r)+       ||]++    Tip arr mx dx -> [|| Tip arr $$(sequenceMaybe mx) $$(sequenceCode1 dx) ||]++    Nil           -> [|| Nil ||]++++sequenceMaybe :: Quote m => Maybe (Code m a) -> Code m (Maybe a)+sequenceMaybe mx =+  case mx of+    Just x  -> [|| Just $$(x) ||]+    Nothing -> [|| Nothing ||]
− src/Data/RadixTree.hs
@@ -1,33 +0,0 @@-------------------------------------------------------------------------------- |--- Module      :  Data.RadixTree--- Copyright   :  (c) Sergey Vinokurov 2018--- License     :  BSD3-style (see LICENSE)--- Maintainer  :  serg.foo@gmail.com------ This is an implementation of the radix tree datastructure. Interface--- is designed to be compatible with what 'Data.Map' provides.-------------------------------------------------------------------------------module Data.RadixTree-  (  RadixTree-  , empty-  , null-  , size-  , insert-  , insertWith-  , lookup-  , fromList-  , toList-  , toAscList-  , keys-  , keysSet-  , elems-  , mapMaybe-  , union-  , unionWith-  ) where--import Prelude hiding (lookup, null)--import Data.RadixTree.Internal
− src/Data/RadixTree/Internal.hs
@@ -1,454 +0,0 @@-------------------------------------------------------------------------------- |--- Module      :  Data.RadixTree.Internal--- Copyright   :  (c) Sergey Vinokurov 2018--- License     :  BSD3-style (see LICENSE)--- Maintainer  :  serg.foo@gmail.com------ This is an internal module that exposes innards of the 'RadixTree'--- data structure. This API may change in any new release, even in a--- patch release - depend on it at your own risk.-------------------------------------------------------------------------------{-# LANGUAGE BangPatterns        #-}-{-# LANGUAGE CPP                 #-}-{-# LANGUAGE DeriveFoldable      #-}-{-# LANGUAGE DeriveFunctor       #-}-{-# LANGUAGE DeriveGeneric       #-}-{-# LANGUAGE DeriveTraversable   #-}-{-# LANGUAGE LambdaCase          #-}-{-# LANGUAGE MagicHash           #-}-{-# LANGUAGE ScopedTypeVariables #-}--{-# OPTIONS_HADDOCK not-home #-}--module Data.RadixTree.Internal-  ( RadixTree(..)-  , empty-  , null-  , size-  , insert-  , insertWith-  , lookup-  , fromList-  , toList-  , toAscList-  , keys-  , keysSet-  , elems-  , mapMaybe-  , union-  , unionWith-  ) where--import Prelude hiding (lookup, null)--import Control.Arrow (first)-import Control.DeepSeq-import Control.Monad.ST-import Control.Monad.ST.Unsafe--import Data.ByteString.Short (ShortByteString)-import qualified Data.ByteString.Short as BSS-import qualified Data.ByteString.Short.Internal as BSSI-import qualified Data.Foldable as Foldable-import Data.IntMap (IntMap)-import qualified Data.IntMap.Strict as IM-import qualified Data.List as L-import Data.Maybe (fromMaybe)-import Data.Primitive.ByteArray-import Data.Semigroup as Semigroup-import Data.Set (Set)-import qualified Data.Set as S-import Data.Word-import GHC.Generics (Generic)---- | A tree data structure that efficiently indexes values by string keys.------ This type can be more memory-efficient than 'Data.Map' because it combines--- common prefixes of all keys. Specific savings will vary depending on--- concrete data set.-data RadixTree a-  = RadixNode-      !(Maybe a)-      !(IntMap (RadixTree a)) -- ^ Either has 0 or 2 or more children, never 1.-  | RadixStr-      !(Maybe a)-      {-# UNPACK #-} !ShortByteString -- ^ Non-empty-      !(RadixTree a)-  deriving (Show, Functor, Foldable, Traversable, Generic)--instance NFData a => NFData (RadixTree a)---- | Radix tree with no elements.-empty :: RadixTree a-empty = RadixNode Nothing IM.empty--{-# INLINE interleaveST #-}-interleaveST :: ST s a -> ST s a-interleaveST =-#if MIN_VERSION_base(4, 10, 0)-    unsafeDupableInterleaveST-#else-    unsafeInterleaveST-#endif--splitShortByteString :: Int -> ShortByteString -> (ShortByteString, ShortByteString, Word8, ShortByteString)-splitShortByteString n (BSSI.SBS source) = runST $ do-  prefix <- newByteArray prefixSize-  copyByteArray prefix 0 source' 0 prefixSize-  ByteArray prefix# <- unsafeFreezeByteArray prefix-  midSuffix         <- interleaveST $ do-    midSuffix <- newByteArray midSuffixSize-    copyByteArray midSuffix 0 source' n midSuffixSize-    unsafeFreezeByteArray midSuffix-  suffix            <- interleaveST $ do-    suffix <- newByteArray suffixSize-    copyByteArray suffix 0 source' (n + 1) suffixSize-    unsafeFreezeByteArray suffix-  pure (BSSI.SBS prefix#, byteArrayToBSS midSuffix, indexByteArray source' n, byteArrayToBSS suffix)-  where-    source' = ByteArray source-    prefixSize = n-    midSuffixSize = sizeofByteArray source' - prefixSize-    suffixSize = midSuffixSize - 1--{-# INLINE byteArrayToBSS #-}-byteArrayToBSS :: ByteArray -> BSS.ShortByteString-byteArrayToBSS (ByteArray xs) = BSSI.SBS xs--dropShortByteString :: Int -> ShortByteString -> ShortByteString-dropShortByteString 0  src = src-dropShortByteString !n (BSSI.SBS source) = runST $ do-  dest <- newByteArray sz-  copyByteArray dest 0 source' n sz-  byteArrayToBSS <$> unsafeFreezeByteArray dest-  where-    source' = ByteArray source-    !sz = sizeofByteArray source' - n--singletonShortByteString :: Word8 -> ShortByteString-singletonShortByteString !c = runST $ do-  dest <- newByteArray 1-  writeByteArray dest 0 c-  byteArrayToBSS <$> unsafeFreezeByteArray dest--{-# INLINE unsafeHeadeShortByteString #-}-unsafeHeadeShortByteString :: ShortByteString -> Word8-unsafeHeadeShortByteString = (`BSSI.unsafeIndex` 0)--data Mismatch-  = IsPrefix-  | CommonPrefixThenMismatch-      !ShortByteString -- ^ Prefix of node contents common with the key-      ShortByteString  -- ^ Suffix with the first mismatching byte-      Word8            -- ^ First byte of the suffix that caused mismatch-      ShortByteString  -- ^ Rest of node contents, suffix-  deriving (Show, Generic)--analyseMismatch-  :: ShortByteString -- ^ Key-  -> Int             -- ^ Key offset-  -> ShortByteString -- ^ Node contents-  -> Mismatch-analyseMismatch (BSSI.SBS key) !keyOffset nodeContentsBS@(BSSI.SBS nodeContents) =-  case findMismatch 0 of-    Nothing          -> IsPrefix-    Just mismatchIdx ->-      case splitShortByteString mismatchIdx nodeContentsBS of-        (prefix, midSuffix, mid, suffix) -> CommonPrefixThenMismatch prefix midSuffix mid suffix-  where-    keySize      = sizeofByteArray key'-    keyLeft      = keySize - keyOffset-    contentsSize = sizeofByteArray nodeContents'--    key'          = ByteArray key-    nodeContents' = ByteArray nodeContents--    limit :: Int-    limit = min keyLeft contentsSize--    findMismatch :: Int -> Maybe Int-    findMismatch !i-      | i == limit-      = if i == contentsSize-        then Nothing-        else Just i -- Key ended in the middle of node's packed key.-      | (indexByteArray key' (keyOffset + i) :: Word8) == indexByteArray nodeContents' i-      = findMismatch $ i + 1-      | otherwise-      = Just i--mkRadixNodeFuse :: Maybe a -> IntMap (RadixTree a) -> Maybe (RadixTree a)-mkRadixNodeFuse val children =-  case val of-    Nothing | IM.null children-      -> Nothing-    val'    | [(c, child)] <- IM.toList children-      -> Just $ RadixStr val' (singletonShortByteString $ fromIntegral c) child-    _ -> Just $ RadixNode val children---- Precondition: input string is non-empty-mkRadixStrFuse :: Maybe a -> ShortByteString -> RadixTree a -> Maybe (RadixTree a)-mkRadixStrFuse val str rest =-  case (val, rest) of-    (val',    RadixStr Nothing str' rest') ->-      Just $ RadixStr val' (str Semigroup.<> str') rest'-    (Nothing, node)-      | null node -> Nothing-    (val', rest') ->-      Just $ RadixStr val' str rest'--mkRadixStr :: ShortByteString -> RadixTree a -> RadixTree a-mkRadixStr str rest-  | BSS.null str = rest-  | otherwise    = RadixStr Nothing str rest---- TODO: prove following function correct.---- | Check whether radix tree is empty-null :: RadixTree a -> Bool-null = \case-  RadixNode Nothing children -> IM.null children-  RadixStr Nothing _ rest    -> null rest-  _                          -> False---- | O(n) Get number of elements in a radix tree.-size :: RadixTree a -> Int-size = length---- | Add new element to a radix tree.-insert :: forall a. ShortByteString -> a -> RadixTree a -> RadixTree a-insert = insertWith const---- | Add new element to a radix tree. If an element was already present for--- the given key, use supplied funciton @f@ to produce a new value. The--- function will be called like this @f newValue oldValue@.-insertWith :: forall a. (a -> a -> a) -> ShortByteString -> a -> RadixTree a -> RadixTree a-insertWith = insert'--{-# INLINE insert' #-}-insert' :: forall a. (a -> a -> a) -> ShortByteString -> a -> RadixTree a -> RadixTree a-insert' f key value = go 0-  where-    len = BSS.length key--    readKey :: Int -> Int-    readKey = fromIntegral . BSSI.unsafeIndex key--    go :: Int -> RadixTree a -> RadixTree a-    go i-      | i < len-      = \case-        RadixNode oldValue children-          | IM.null children ->-            RadixStr oldValue (dropShortByteString i key) $ RadixNode (Just value) IM.empty-          | otherwise ->-            RadixNode oldValue $-            IM.alter (Just . maybe optNode (go i')) c children-          where-            c :: Int-            c = readKey i-            i' = i + 1-            optNode =-              mkRadixStr (dropShortByteString i' key) $ RadixNode (Just value) IM.empty-        RadixStr oldValue packedKey rest ->-          case analyseMismatch key i packedKey of-            IsPrefix ->-              RadixStr oldValue packedKey $ go (i + BSS.length packedKey) rest-            CommonPrefixThenMismatch prefix midSuffix mid suffix ->-              (if BSS.null prefix then id else RadixStr oldValue prefix) $-                if isKeyEnded-                then-                  RadixStr (Just value) midSuffix rest-                else-                  RadixNode (if BSS.null prefix then oldValue else Nothing) $-                  IM.fromList-                    [ ( mid'-                      , mkRadixStr suffix rest-                      )-                    , ( readKey i'-                      , mkRadixStr (dropShortByteString (i' + 1) key) $ RadixNode (Just value) IM.empty-                      )-                    ]-              where-                i'         = i + BSS.length prefix-                isKeyEnded = i' >= len-                mid'       = fromIntegral mid-      | otherwise-      = \case-        RadixNode oldValue children ->-          RadixNode (Just (maybe value (f value) oldValue)) children-        RadixStr oldValue key' rest ->-          RadixStr (Just (maybe value (f value) oldValue)) key' rest--canStripPrefixFromShortByteString-  :: Int -> ShortByteString -> ShortByteString -> Bool-canStripPrefixFromShortByteString bigStart (BSSI.SBS small) (BSSI.SBS big)-  | bigStart + smallSize > bigSize = False-  | otherwise                      = findMismatch 0-  where-    small' = ByteArray small-    big'   = ByteArray big--    smallSize = sizeofByteArray small'-    bigSize   = sizeofByteArray big'--    findMismatch :: Int -> Bool-    findMismatch !i-      | i == smallSize-      = True-      | (indexByteArray small' i :: Word8) == indexByteArray big' (bigStart + i)-      = findMismatch $ i + 1-      | otherwise-      = False---- | O(length(key)) Try to find a value associated with the given key.-lookup :: forall a. ShortByteString -> RadixTree a -> Maybe a-lookup key = go 0-  where-    len = BSS.length key--    readKey :: Int -> Int-    readKey = fromIntegral . BSSI.unsafeIndex key--    go :: Int -> RadixTree a -> Maybe a-    go !n tree-      | n == len-      = case tree of-        RadixNode val _  -> val-        RadixStr val _ _ -> val-      | otherwise-      = case tree of-      RadixNode _ children      ->-        IM.lookup (readKey n) children >>= go (n + 1)-      RadixStr _ packedKey rest-        | canStripPrefixFromShortByteString n packedKey key-        -> go (n + BSS.length packedKey) rest-        | otherwise-        -> Nothing---- | Construct a radix tree from list of key-value pairs. If some key--- appears twice in the input list, later occurrences will override--- earlier ones.-fromList :: [(ShortByteString, a)] -> RadixTree a-fromList =-  L.foldl' (\acc (k, v) -> insert' const k v acc) empty---- | O(n) Convert a radix tree to a list of key-value pairs.-toList :: RadixTree a -> [(ShortByteString, a)]-toList = toAscList---- | O(n) Convert a radix tree to an ascending list of key-value pairs.-toAscList :: forall a. RadixTree a -> [(ShortByteString, a)]-toAscList = map (first BSS.pack) . go-  where-    go :: RadixTree a -> [([Word8], a)]-    go = \case-      RadixNode val children ->-        maybe id (\val' ys -> ([], val') : ys) val $-        IM.foldMapWithKey (\c child -> map (first (fromIntegral c :)) $ go child) children-      RadixStr val packedKey rest ->-        maybe id (\val' ys -> ([], val') : ys) val $-        map (first (BSS.unpack packedKey ++)) $-        go rest---- | O(n) Get all keys stored in a radix tree.-keys :: RadixTree a -> [ShortByteString]-keys = map BSS.pack . go-  where-    go :: RadixTree a -> [[Word8]]-    go = \case-      RadixNode val children ->-        maybe id (\_ ys -> [] : ys) val $-        IM.foldMapWithKey (\c child -> map (fromIntegral c :) $ go child) children-      RadixStr val packedKey rest ->-        maybe id (\_ ys -> [] : ys) val $-        map (BSS.unpack packedKey <>) $-        go rest---- | O(n) Get set of all keys stored in a radix tree.-keysSet :: RadixTree a -> Set ShortByteString-keysSet = S.fromDistinctAscList . keys---- | O(n) Get all values stored in a radix tree.-elems :: RadixTree a -> [a]-elems = Foldable.toList---- | O(n) Map a function that can remove some existing elements over a--- radix tree.-mapMaybe :: forall a b. (a -> Maybe b) -> RadixTree a -> RadixTree b-mapMaybe f = fromMaybe empty . go-  where-    go :: RadixTree a -> Maybe (RadixTree b)-    go = \case-      RadixNode val children ->-        mkRadixNodeFuse (f =<< val) $ IM.mapMaybe go children-      RadixStr val str rest ->-        mkRadixStrFuse (f =<< val) str $ fromMaybe empty $ go rest---- | O(n + m) Combine two radix trees trees. If a key is present in both--- trees then the value from left one will be retained.-union :: RadixTree a -> RadixTree a -> RadixTree a-union = unionWith const---- | O(n + m) Combine two trees using supplied function to resolve--- values that have the same key in both trees.-unionWith :: forall a. (a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a-unionWith f = go-  where-    combineVals :: Maybe a -> Maybe a -> Maybe a-    combineVals x y = case (x, y) of-      (Nothing,   Nothing)   -> Nothing-      (Nothing,   y'@Just{}) -> y'-      (x'@Just{}, Nothing)   -> x'-      (Just x',   Just y')   -> Just $ f x' y'--    go :: RadixTree a -> RadixTree a -> RadixTree a-    go x y = case (x, y) of-      (RadixNode val children, RadixNode val' children') ->-        RadixNode (combineVals val val') (IM.unionWith go children children')-      (RadixNode val children, RadixStr val' str' rest') ->-        RadixNode (combineVals val val') $-          (\g -> IM.alter g h children) $ \child ->-            Just $!-            let rest'' = mkRadixStr (dropShortByteString 1 str') rest' in-            case child of-              Nothing     -> rest''-              Just child' -> go child' rest''-        where-          h = fromIntegral $ unsafeHeadeShortByteString str'-      (RadixStr val str rest, RadixNode val' children') ->-        RadixNode (combineVals val val') $-          (\g -> IM.alter g h children') $ \child ->-            Just $!-            let rest' = mkRadixStr (dropShortByteString 1 str) rest in-            case child of-              Nothing     -> rest'-              Just child' -> go rest' child'-        where-          h = fromIntegral $ unsafeHeadeShortByteString str-      (RadixStr val str rest, RadixStr val' str' rest') ->-        case analyseMismatch str 0 str' of-          -- str' is a prefix of str-          IsPrefix ->-            RadixStr (combineVals val val') str' $-              go (mkRadixStr (dropShortByteString (BSS.length str') str) rest) rest'-          -- str' = prefix + firstMismatchStr' + suffixStr'-          --      = prefix + midSuffixStr'-          CommonPrefixThenMismatch prefix midSuffixStr' firstMismatchStr' suffixStr' ->-            (if BSS.null prefix then id else RadixStr (combineVals val val') prefix) $-              if BSS.length prefix == BSS.length str-              then-                go rest $ RadixStr-                  (if BSS.null prefix then combineVals val val' else Nothing)-                  midSuffixStr'-                  rest'-              else RadixNode (if BSS.null prefix then combineVals val val' else Nothing) $ IM.fromList-                [ ( fromIntegral firstMismatchStr'-                  , mkRadixStr suffixStr' rest'-                  )-                , ( fromIntegral $ BSSI.unsafeIndex str $ BSS.length prefix-                  , mkRadixStr (dropShortByteString (BSSI.length prefix + 1) str) rest-                  )-                ]
+ src/Data/RadixTree/Word8/Key.hs view
@@ -0,0 +1,90 @@+{-|+    Safe functions for building and destroying radix tree keys.+ -}++module Data.RadixTree.Word8.Key+  ( -- * Build+    Build++    -- ** Raw+  , buildBytes++    -- ** ByteString+  , buildByteString+  , buildShortByteString++    -- ** Text+    -- | See "Data.RadixTree.Word8.Key.Unsafe#g:build/text".++    -- * Feed+  , Feed++    -- ** Raw+  , feedBytes++    -- ** ByteString+  , feedByteString+  , feedShortByteString+  , feedLazyByteString++    -- ** Text+  , feedText+  , feedLazyText+  ) where++import           Data.RadixNTree.Word8.Key++import qualified Data.ByteString as Strict (ByteString)+import qualified Data.ByteString.Lazy as Lazy (ByteString)+import           Data.ByteString.Short (ShortByteString)+import qualified Data.Text as Strict (Text)+import qualified Data.Text.Lazy as Lazy (Text)+import           Data.Word++++-- | Convert a key into a list of bytes.+buildBytes :: Build -> [Word8]+buildBytes = buildBytes0++-- | Convert a key into a strict 'Strict.ByteString'.+buildByteString :: Build -> Strict.ByteString+buildByteString = buildByteString0++-- | Convert a key into a 'ShortByteString'.+buildShortByteString :: Build -> ShortByteString+buildShortByteString = buildShortByteString0++++{-# INLINE feedBytes #-}+-- | Convert a list of bytes into a key.+feedBytes :: [Word8] -> Feed+feedBytes = feedBytes0++{-# INLINE feedByteString #-}+-- | Convert a strict 'Strict.ByteString' into a key.+feedByteString :: Strict.ByteString -> Feed+feedByteString = feedByteString0++{-# INLINE feedShortByteString #-}+-- | Convert a 'ShortByteString' into a key.+feedShortByteString :: ShortByteString -> Feed+feedShortByteString = feedShortByteString0++{-# INLINE feedLazyByteString #-}+-- | Convert a lazy 'Lazy.ByteString' into a key.+feedLazyByteString :: Lazy.ByteString -> Feed+feedLazyByteString = feedLazyByteString0++++{-# INLINE feedText #-}+-- | Convert a strict 'Strict.Text' into a key.+feedText :: Strict.Text -> Feed+feedText = feedText0++{-# INLINE feedLazyText #-}+-- | Convert a lazy 'Lazy.Text' into a key.+feedLazyText :: Lazy.Text -> Feed+feedLazyText = feedLazyText0
+ src/Data/RadixTree/Word8/Key/Unsafe.hs view
@@ -0,0 +1,32 @@+{-# OPTIONS_HADDOCK not-home #-}++{-|+    Radix tree key internals, and unsafe functions for building and destroying them.+ -}++module Data.RadixTree.Word8.Key.Unsafe+  ( -- * Build+    Build (..)+  , Tsil (..)++    -- ** Text #build/text#+  , unsafeBuildText++    -- * Feed+  , Feed (..)+  , Step (..)+  ) where++import           Data.ByteArray.NonEmpty (Step (..))+import           Data.RadixNTree.Word8.Key++import qualified Data.Text as Strict (Text)++++-- | Convert a key into a strict 'Strict.Text'.+--+--   No checks are made to ensure the resulting value is a valid sequence+--   of UTF-8 code units.+unsafeBuildText :: Build -> Strict.Text+unsafeBuildText = unsafeBuildText0
+ src/Data/RadixTree/Word8/Lazy.hs view
@@ -0,0 +1,789 @@+{-|+    @'LazyRadixTree' a@ is a spine-lazy radix tree that uses byte-aligned+    byte sequences as keys.++    == Laziness++    Evaluating any particular entry in the tree to WHNF forces the evaluation+    of the part of the spine leading up to that entry to normal form.++    == Performance++    Each function's time complexity is provided in the documentation.++    Laziness-amortized functions specify two time complexities:+    time to construct the return value (denoted with a \(\texttt{+}\)) and time to+    fully apply the function to the tree.++    \(x\) is the length of the input key.++    \(k\) is the length of the longest key stored in the tree.++    \(n\) refers to the total number of entries in the tree.+    Parts of the tree are denoted using subscripts: \(n_L\) refers to the left side,+    \(n_R\) to the right side, and \(n_M\) to entries collected with the use of a 'Monoid'.++    == Inlining++    Functions that produce and consume 'Feed's are treated specially within the library,+    as when combined they can be reduced in a manner similar to the+    [destroy/unfoldr elimination rule](https://wiki.haskell.org/Correctness_of_short_cut_fusion#destroy.2Funfoldr).++    The elimination in this library is achieved by inlining both types of functions+    heavily. To avoid unnecessary code duplication during compilation consider creating+    helper functions that apply these functions one to another, e.g.++    @updateBS f bs = 'update' f ('Data.RadixTree.Word8.Key.feedByteString' bs)@++    N.B. To inline properly functions that consume 'Feed's must mention all of the+         arguments except for the tree.++    == Implementation++    See the implementation section in "Data.RadixTree.Word8.Strict.Unsafe"+    for the explanation of the innerworkings.++    See the implementation section in "Data.Patricia.Word.Strict" for literary references.+ -}++module Data.RadixTree.Word8.Lazy+  ( LazyRadixTree+  , RadixTree (..)++    -- * Key+  , module Data.RadixTree.Word8.Key++    -- * Construct+  , empty+  , singleton++    -- ** Convert+  , toStrict++    -- * Single-key+    -- ** Lookup+  , Data.RadixTree.Word8.Lazy.lookup+  , Data.RadixTree.Word8.Lazy.find+  , Data.RadixTree.Word8.Lazy.member+  , subtree++    -- *** Chunked+    --+    -- | Chunked lookup allows providing the key piece by piece while retaining+    --   the ability to check for early failure.+    --+    --   Note that while 'subtree' can be used to achieve the same result,+    --   it is more expensive allocation-wise, as it must ensure that+    --   the resulting tree is well-formed after each chunk application.+  , Cursor+  , cursor+  , move+  , stop+  , Location (..)+  , locate++    -- ** Insert+  , insert+  , insertWith++    -- ** Map+  , adjust++    -- ** Delete+  , delete+  , prune++    -- ** Update+  , update+  , alter+  , shape++    -- ** Take+  , splitLookup++    -- * Directional+  , Openness (..)++    -- ** Lookup+  , Lookup (..)+  , lookupL+  , lookupR++    -- ** Map+    -- | === Left+  , adjustL+  , adjustLWithKey++    -- | === Right+  , adjustR+  , adjustRWithKey++    -- ** Update+    -- | === Left+  , updateL+  , updateLWithKey++    -- | === Right+  , updateR+  , updateRWithKey++    -- ** Take+    -- | === Left+  , takeL+  , splitL++    -- | === Right+  , takeR++    -- * Edges++    -- ** Lookup+    -- | === Min+  , lookupMin+  , lookupMinWithKey++    -- | === Max+  , lookupMax+  , lookupMaxWithKey++    -- ** Map+    -- | === Min+  , adjustMin+  , adjustMinWithKey++    -- | === Max+  , adjustMax+  , adjustMaxWithKey++    -- ** Delete+  , deleteMin+  , deleteMax++    -- ** Update+    -- | === Min+  , updateMin+  , updateMinWithKey++    -- | === Max+  , updateMax+  , updateMaxWithKey++    -- ** View+    -- | === Min+  , ViewL (..)+  , minView++    -- | === Max+  , ViewR (..)+  , maxView++    -- * Full tree+    -- ** Size+  , Data.RadixTree.Word8.Lazy.null+  , size++    -- ** Extend+  , prefix++    -- ** Map+  , Data.RadixTree.Word8.Lazy.map+  , mapWithKey++    -- ** Fold+    -- | === Left-to-right+  , Data.RadixTree.Word8.Lazy.foldl+  , Data.RadixTree.Word8.Lazy.foldl'+  , foldlWithKey+  , foldlWithKey'++    -- | === Right-to-left+  , Data.RadixTree.Word8.Lazy.foldr+  , Data.RadixTree.Word8.Lazy.foldr'+  , foldrWithKey+  , foldrWithKey'++    -- | === Monoid+  , Data.RadixTree.Word8.Lazy.foldMap+  , foldMapWithKey++    -- ** Traverse+  , Data.RadixTree.Word8.Lazy.traverse+  , traverseWithKey++    -- ** Filter+    -- | === One side+  , Data.RadixTree.Word8.Lazy.filter+  , filterWithKey++  , mapMaybe+  , mapMaybeWithKey++    -- | === Both sides+  , partition+  , partitionWithKey++  , mapEither+  , mapEitherWithKey++    -- ** Comparison+  , PartialOrdering (..)+  , Data.RadixTree.Word8.Lazy.compare++    -- ** Union+  , union+  , unionL+  , unionWith+  , unionWithKey++    -- ** Difference+  , difference+  , differenceWith+  , differenceWithKey++    -- ** Intersection+  , disjoint+  , intersection+  , intersectionL+  , intersectionWith+  , intersectionWithKey++    -- ** Merge+    -- | See 'Data.RadixTree.Word8.Lazy.Unsafe.merge'.+  ) where++import           Data.RadixTree.Word8.Key+import           Data.RadixNTree.Word8.Common+import           Data.RadixNTree.Word8.Conversion+import           Data.RadixNTree.Word8.Lazy+import           Radix.Common++++-- | \(\mathcal{O}(1)\).+--   Empty tree.+empty :: RadixTree a+empty = empty0++{-# INLINE singleton #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(x)\).+--   Tree with a single entry.+singleton :: Feed -> a -> RadixTree a+singleton = singleton0+++-- | \(\mathcal{O}(n)\).+--   Create a strict 'Strict.Patricia' tree from a lazy one.+--+--   The resulting tree does not share its data representation with the original.+toStrict :: LazyRadixTree a -> StrictRadixTree a+toStrict = toStrict0++++-- | \(\mathcal{O}(1)\).+--   Check if the tree is empty.+null :: RadixTree a -> Bool+null = null0++-- | \(\mathcal{O}(n)\).+--   Calculate the number of elements stored in the tree.+--   The returned number is guaranteed to be non-negative.+size :: RadixTree a -> Int+size = size0++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree.+map :: (a -> b) -> RadixTree a -> RadixTree b+map = map0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree.+mapWithKey :: (Build -> a -> b) -> RadixTree a -> RadixTree b+mapWithKey = mapWithKey0++++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldl :: (b -> a -> b) -> b -> RadixTree a -> b+foldl = Data.RadixNTree.Word8.Lazy.foldl0++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldlWithKey :: (b -> Build -> a -> b) -> b -> RadixTree a -> b+foldlWithKey = foldlWithKey0++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldl' :: (b -> a -> b) -> b -> RadixTree a -> b+foldl' = foldl0'++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldlWithKey' :: (b -> Build -> a -> b) -> b -> RadixTree a -> b+foldlWithKey' = foldlWithKey0'++++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldr :: (a -> b -> b) -> b -> RadixTree a -> b+foldr = Data.RadixNTree.Word8.Lazy.foldr0++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldrWithKey :: (Build -> a -> b -> b) -> b -> RadixTree a -> b+foldrWithKey = foldrWithKey0++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldr' :: (a -> b -> b) -> b -> RadixTree a -> b+foldr' = foldr0'++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldrWithKey' :: (Build -> a -> b -> b) -> b -> RadixTree a -> b+foldrWithKey' = foldrWithKey0'++++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMap :: Monoid m => (a -> m) -> RadixTree a -> m+foldMap = foldMap0++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMapWithKey :: Monoid m => (Build -> a -> m) -> RadixTree a -> m+foldMapWithKey = foldMapWithKey0++++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverse :: Applicative f => (a -> f b) -> RadixTree a -> f (RadixTree b)+traverse = traverse0++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverseWithKey+  :: Applicative f => (Build -> a -> f b) -> RadixTree a -> f (RadixTree b)+traverseWithKey = traverseWithKey0++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filter :: (a -> Bool) -> RadixTree a -> RadixTree a+filter = filter0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filterWithKey :: (Build -> a -> Bool) -> RadixTree a -> RadixTree a+filterWithKey = filterWithKey0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create one out of 'Just' values.+mapMaybe :: (a -> Maybe b) -> RadixTree a -> RadixTree b+mapMaybe = mapMaybe0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create one out of 'Just' values.+mapMaybeWithKey :: (Build -> a -> Maybe b) -> RadixTree a -> RadixTree b+mapMaybeWithKey = mapMaybeWithKey0+++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Split the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partition :: (a -> Bool) -> RadixTree a -> (RadixTree a, RadixTree a)+partition = partition0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Split the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partitionWithKey :: (Build -> a -> Bool) -> RadixTree a -> (RadixTree a, RadixTree a)+partitionWithKey = partitionWithKey0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+mapEither :: (a -> Either b c) -> RadixTree a -> (RadixTree b, RadixTree c)+mapEither = mapEither0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+mapEitherWithKey :: (Build -> a -> Either b c) -> RadixTree a -> (RadixTree b, RadixTree c)+mapEitherWithKey = mapEitherWithKey0++++{-# INLINE lookup #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the value at a key in the tree.+lookup :: Feed -> RadixTree a -> Maybe a+lookup = lookup0++{-# INLINE find #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the value at a key in the tree, falling back to the given default value+--   if it does not exist.+find :: a -> Feed -> RadixTree a -> a+find = find0++{-# INLINE member #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Check whether the value exists at a key in the tree.+member :: Feed -> RadixTree a -> Bool+member = member0++{-# INLINE subtree #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the part of the tree below the given prefix.+subtree :: Feed -> RadixTree a -> RadixTree a+subtree = subtree0++{-# INLINE prefix #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(x)\).+--   Prefix the root of the tree with the given key.+prefix :: Feed -> RadixTree a -> RadixTree a+prefix = prefix0+++-- | \(\mathcal{O}(1)\).+--   Make a cursor that points to the root of the tree.+cursor :: RadixTree a -> Cursor a+cursor = cursor0++{-# INLINE move #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Move the cursor down by the extent of the given key.+move :: Feed -> Cursor a -> Cursor a+move = move0++++{-# INLINE insert #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, it is replaced.+insert :: Feed -> a -> RadixTree a -> RadixTree a+insert = insert0++{-# INLINE insertWith #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, the function is used instead.+insertWith :: (a -> a) -> Feed -> a -> RadixTree a -> RadixTree a+insertWith = insertWith0+++{-# INLINE adjust #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Apply a function to a value in the tree at the given key.+adjust :: (a -> a) -> Feed -> RadixTree a -> RadixTree a+adjust = adjust0+++{-# INLINE delete #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Delete a value in the tree at the given key.+delete :: Feed -> RadixTree a -> RadixTree a+delete = delete0++{-# INLINE prune #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Delete values in the tree below the given key.+prune :: Openness -> Feed -> RadixTree a -> RadixTree a+prune = prune0+++{-# INLINE update #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Update or delete a value in the tree at the given key.+update :: (a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a+update = update0+++{-# INLINE alter #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Insert, update or delete a value in the tree at the given key.+alter :: (Maybe a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a+alter = alter0+++{-# INLINE shape #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Update the part of the tree at the given prefix.+shape :: (RadixTree a -> RadixTree a) -> Feed -> RadixTree a -> RadixTree a+shape = shape0+++{-# INLINE splitLookup #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Split the tree into two, such that+--   values with keys smaller than the given one are on the left,+--   values with keys greater than the given one are on the right,+--   and the value at the given key is returned separately.+splitLookup :: Feed -> RadixTree a -> (RadixTree a, Maybe a, RadixTree a)+splitLookup = splitLookup0++++{-# INLINE lookupL #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up a value at a largest key smaller than (or equal to) the given key.+lookupL :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)+lookupL = lookupL0+++{-# INLINE lookupR #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up a value at a smallest key greater than (or equal to) the given key.+lookupR :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)+lookupR = lookupR0++++{-# INLINE adjustL #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+adjustL :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustL = adjustL0++{-# INLINE adjustLWithKey #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+adjustLWithKey :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustLWithKey = adjustLWithKey0++++{-# INLINE adjustR #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+adjustR :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustR = adjustR0++{-# INLINE adjustRWithKey #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+adjustRWithKey :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustRWithKey = adjustRWithKey0++++{-# INLINE updateL #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_L)\).+--   Update every value for which the key is smaller than (or equal to) the given one.+updateL :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateL = updateL0++{-# INLINE updateLWithKey #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_L)\).+--   Update every value for which the key is smaller than (or equal to) the given one.+updateLWithKey :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateLWithKey = updateLWithKey0++{-# INLINE updateR #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_R)\).+--   Update every value for which the key is greater than (or equal to) the given one.+updateR :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateR = updateR0++{-# INLINE updateRWithKey #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k) + n_R)\).+--   Update every value for which the key is greater than (or equal to) the given one.+updateRWithKey :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateRWithKey = updateRWithKey0++++{-# INLINE takeL #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Take values for which keys are smaller than (or equal to) the given one.+takeL :: Openness -> Feed -> RadixTree a -> RadixTree a+takeL = takeL0++{-# INLINE takeR #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Take values for which keys are greater than (or equal to) the given one.+takeR :: Openness -> Feed -> RadixTree a -> RadixTree a+takeR = takeR0++++{-# INLINE splitL #-}+-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(\min(x,k))\).+--   Split the tree into two, such that+--   values with keys smaller than (or equal to) the given one are on the left,+--   and the rest are on the right.+splitL :: Openness -> Feed -> RadixTree a -> (RadixTree a, RadixTree a)+splitL = splitL0++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+lookupMin :: RadixTree a -> Maybe a+lookupMin = lookupMin0++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+lookupMinWithKey :: RadixTree a -> Maybe (Lookup a)+lookupMinWithKey = lookupMinWithKey0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Delete a value at the leftmost key in the tree.+deleteMin :: RadixTree a -> RadixTree a+deleteMin = deleteMin0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+adjustMin :: (a -> a) -> RadixTree a -> RadixTree a+adjustMin = adjustMin0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+adjustMinWithKey :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMinWithKey = adjustMinWithKey0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+updateMin :: (a -> Maybe a) -> RadixTree a -> RadixTree a+updateMin = updateMin0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+updateMinWithKey :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a+updateMinWithKey = updateMinWithKey0++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the leftmost value and return it alongside the tree without it.+minView :: RadixTree a -> Maybe (ViewL a)+minView = minView0++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+lookupMax :: RadixTree a -> Maybe a+lookupMax = lookupMax0++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+lookupMaxWithKey :: RadixTree a -> Maybe (Lookup a)+lookupMaxWithKey = lookupMaxWithKey0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Delete a value at the rightmost key in the tree.+deleteMax :: RadixTree a -> RadixTree a+deleteMax = deleteMax0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+adjustMax :: (a -> a) -> RadixTree a -> RadixTree a+adjustMax = adjustMax0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+adjustMaxWithKey :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMaxWithKey = adjustMaxWithKey0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+updateMax :: (a -> Maybe a) -> RadixTree a -> RadixTree a+updateMax = updateMax0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+updateMaxWithKey :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a+updateMaxWithKey = updateMaxWithKey0++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the rightmost value and return it alongside the tree without it.+maxView :: RadixTree a -> Maybe (ViewR a)+maxView = maxView0++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Unbiased union of two trees.+union :: RadixTree a -> RadixTree a -> RadixTree a+union = union0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Left-biased union of two trees.+unionL :: RadixTree a -> RadixTree a -> RadixTree a+unionL = unionL0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Union of two trees with a combining function.+unionWith :: (a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a+unionWith = unionWith0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Union of two trees with a combining function.+unionWithKey :: (Build -> a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a+unionWithKey = unionWithKey0++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees.+difference :: RadixTree a -> RadixTree b -> RadixTree a+difference = difference0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees with a combining function.+differenceWith :: (a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a+differenceWith = differenceWith0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees with a combining function.+differenceWithKey+  :: (Build -> a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a+differenceWithKey = differenceWithKey0++++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Compare two trees with respect to set inclusion,+--   using the given equality function for intersecting keys.+--   If any intersecting keys hold unequal values, the trees are 'Incomparable'.+compare :: (a -> b -> Bool) -> RadixTree a -> RadixTree b -> PartialOrdering+compare = compare0++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Determine whether two trees' key sets are disjoint.+disjoint :: RadixTree a -> RadixTree b -> Bool+disjoint = disjoint0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Unbiased intersection of two trees.+intersection :: RadixTree a -> RadixTree a -> RadixTree a+intersection = intersection0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Left-biased intersection of two trees.+intersectionL :: RadixTree a -> RadixTree b -> RadixTree a+intersectionL = intersectionL0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Intersection of two trees with a combining function.+intersectionWith :: (a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c+intersectionWith = intersectionWith0++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   Intersection of two trees with a combining function.+intersectionWithKey :: (Build -> a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c+intersectionWithKey = intersectionWithKey0
+ src/Data/RadixTree/Word8/Lazy/Debug.hs view
@@ -0,0 +1,30 @@+{-|+    Safe functions for datatype introspection.+ -}++module Data.RadixTree.Word8.Lazy.Debug+  ( -- * Show+    showsTree++    -- * Validate+  , Validity (..)+  , Reason (..)+  , validate+  ) where++import           Data.RadixNTree.Word8.Lazy (RadixTree)+import           Data.RadixNTree.Word8.Lazy.Debug++++-- | \(\mathcal{O}(n)\).+--   Shows the internal structure of the tree.+showsTree :: (a -> ShowS) -> RadixTree a -> ShowS+showsTree = showsTree0++++-- | \(\mathcal{O}(n)\).+--   Checks whether the tree is well-formed.+validate :: RadixTree a -> Validity+validate = validate0
+ src/Data/RadixTree/Word8/Lazy/TH.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE TemplateHaskellQuotes #-}++{-|+    Template Haskell helper functions.+ -}++module Data.RadixTree.Word8.Lazy.TH+  ( sequenceCode+  ) where++import           Data.RadixNTree.Word8.Lazy.TH++import           Language.Haskell.TH.Syntax++++-- | \(\mathcal{O}(n)\).+--   Evaluate a tree of typed expressions.+sequenceCode :: Quote m => RadixTree (Code m a) -> Code m (RadixTree a)+sequenceCode = sequenceCode0
+ src/Data/RadixTree/Word8/Lazy/Unsafe.hs view
@@ -0,0 +1,57 @@+{-# OPTIONS_HADDOCK not-home #-}++{-|+    Data structure internals, helper operations and unsafe functions.+ -}++module Data.RadixTree.Word8.Lazy.Unsafe+  ( RadixTree (..)+  , Radix1Tree (..)++    -- * Bit operations+  , Prefix+  , Key++    -- | === Compare+  , beyond+  , upper+  , lower++    -- | === Create+  , Mask+  , zeroBit+  , mask+  , branchingBit++    -- * Exceptions+  , MalformedTree (..)++    -- * Full-tree+    -- ** Merge+  , merge+  ) where++import           Data.RadixNTree.Word8.Key+import           Data.RadixNTree.Word8.Lazy+import           Radix.Exception+import           Radix.Word8.Foundation++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n_A k_A + n_B k_B)\).+--   General merge of two trees.+--+--   Resulting 'Maybe's and 'Radix1Tree's in argument functions are evaluated to WHNF.+--+--   This functions inlines when all argument functions are provided.+{-# INLINE merge #-}+merge+  :: (Build -> a -> b -> Maybe c)            -- ^ Single value collision+  -> (Build -> a -> Maybe c)                 -- ^ Single left value+  -> (Build -> Radix1Tree a -> Radix1Tree c) -- ^ Left subtree+  -> (Build -> b -> Maybe c)                 -- ^ Single right value+  -> (Build -> Radix1Tree b -> Radix1Tree c) -- ^ Right subtree+  -> RadixTree a+  -> RadixTree b+  -> RadixTree c+merge = merge0
+ src/Data/RadixTree/Word8/Strict.hs view
@@ -0,0 +1,926 @@+{-|+    @'StrictRadixTree' a@ is a spine-strict radix tree that uses byte-aligned+    byte sequences as keys.++    == Laziness++    Evaluating the root of the tree (i.e. @(_ :: 'StrictRadixTree' a)@) to+    weak head normal form evaluates the entire spine of the tree to normal form.++    Functions do not perform any additional evaluations unless+    their documentation directly specifies so.++    == Performance++    Each function's time complexity is provided in the documentation.++    \(x\) is the length of the input key.++    \(k\) is the length of the longest key stored in the tree.++    \(n\) refers to the total number of entries in the tree.+    Parts of the tree are denoted using subscripts: \(n_L\) refers to the left side,+    \(n_R\) to the right side, and \(n_M\) to entries collected with the use of a 'Monoid'.++    == Inlining++    Functions that produce and consume 'Feed's are treated specially within the library,+    as when combined they can be reduced in a manner similar to the+    [destroy/unfoldr elimination rule](https://wiki.haskell.org/Correctness_of_short_cut_fusion#destroy.2Funfoldr).++    The elimination in this library is achieved by inlining both types of functions+    heavily. To avoid unnecessary code duplication during compilation consider creating+    helper functions that apply these functions one to another, e.g.++    @updateBS f bs = 'update' f ('Data.RadixTree.Word8.Key.feedByteString' bs)@++    N.B. To inline properly functions that consume 'Feed's must mention all of the+         arguments except for the tree.++    == Implementation++    See the implementation section in "Data.RadixTree.Word8.Strict.Unsafe"+    for the explanation of the innerworkings.++    See the implementation section in "Data.Patricia.Word.Strict" for literary references.+ -}++module Data.RadixTree.Word8.Strict+  ( StrictRadixTree+  , RadixTree (..)++    -- * Key+  , module Data.RadixTree.Word8.Key++    -- * Construct+  , empty+  , singleton++    -- ** Convert+  , toLazy++    -- * Single-key+    -- ** Lookup+  , Data.RadixTree.Word8.Strict.lookup+  , Data.RadixTree.Word8.Strict.find+  , Data.RadixTree.Word8.Strict.member+  , subtree++    -- *** Chunked+    --+    -- | Chunked lookup allows providing the key piece by piece while retaining+    --   the ability to check for early failure.+    --+    --   Note that while 'subtree' can be used to achieve the same result,+    --   it is more expensive allocation-wise, as it must ensure that+    --   the resulting tree is well-formed after each chunk application.+  , Cursor+  , cursor+  , move+  , stop+  , Location (..)+  , locate++    -- ** Insert+  , insert+  , insertWith+  , insertWith'++    -- ** Map+  , adjust+  , adjust'++    -- ** Delete+  , delete+  , prune++    -- ** Update+  , update+  , alter+  , shape++    -- ** Take+  , SplitLookup (..)+  , splitLookup++    -- * Directional+  , Openness (..)++    -- ** Lookup+  , Lookup (..)+  , lookupL+  , lookupR++    -- ** Map+    -- | === Left+  , adjustL+  , adjustL'+  , adjustLWithKey+  , adjustLWithKey'++    -- | === Right+  , adjustR+  , adjustR'+  , adjustRWithKey+  , adjustRWithKey'++    -- ** Update+    -- | === Left+  , updateL+  , updateLWithKey++    -- | === Right+  , updateR+  , updateRWithKey++    -- ** Take+  , Split (..)++    -- | === Left+  , takeL+  , splitL++    -- | === Right+  , takeR++    -- * Edges++    -- ** Lookup+    -- | === Min+  , lookupMin+  , lookupMinWithKey++    -- | === Max+  , lookupMax+  , lookupMaxWithKey++    -- ** Map+    -- | === Min+  , adjustMin+  , adjustMin'+  , adjustMinWithKey+  , adjustMinWithKey'++    -- | === Max+  , adjustMax+  , adjustMax'+  , adjustMaxWithKey+  , adjustMaxWithKey'++    -- ** Delete+  , deleteMin+  , deleteMax++    -- ** Update+    -- | === Min+  , updateMin+  , updateMinWithKey++    -- | === Max+  , updateMax+  , updateMaxWithKey++    -- ** View+    -- | === Min+  , ViewL (..)+  , minView++    -- | === Max+  , ViewR (..)+  , maxView++    -- * Full tree+    -- ** Size+  , Data.RadixTree.Word8.Strict.null+  , size++    -- ** Extend+  , prefix++    -- ** Map+  , Data.RadixTree.Word8.Strict.map+  , map'+  , mapWithKey+  , mapWithKey'++    -- ** Fold+    -- | === Left-to-right+  , Data.RadixTree.Word8.Strict.foldl+  , Data.RadixTree.Word8.Strict.foldl'+  , foldlWithKey+  , foldlWithKey'++    -- | === Right-to-left+  , Data.RadixTree.Word8.Strict.foldr+  , Data.RadixTree.Word8.Strict.foldr'+  , foldrWithKey+  , foldrWithKey'++    -- | === Monoid+  , Data.RadixTree.Word8.Strict.foldMap+  , foldMapWithKey++    -- ** Traverse+  , Data.RadixTree.Word8.Strict.traverse+  , traverseWithKey++    -- ** Filter+    -- | === One side+  , Data.RadixTree.Word8.Strict.filter+  , filterWithKey++  , mapMaybe+  , mapMaybeWithKey++    -- | === Both sides+  , partition+  , partitionWithKey++  , mapEither+  , mapEitherWithKey++    -- ** Comparison+  , PartialOrdering (..)+  , Data.RadixTree.Word8.Strict.compare++    -- ** Union+  , union+  , unionL+  , unionWith'+  , unionWithKey'++    -- ** Difference+  , difference+  , differenceWith+  , differenceWithKey++    -- ** Intersection+  , disjoint+  , intersection+  , intersectionL+  , intersectionWith'+  , intersectionWithKey'++    -- ** Merge+    -- | See 'Data.RadixTree.Word8.Strict.Unsafe.merge'.+  ) where++import           Data.RadixTree.Word8.Key+import           Data.RadixNTree.Word8.Common+import           Data.RadixNTree.Word8.Conversion+import           Data.RadixNTree.Word8.Strict+import           Radix.Common++++-- | \(\mathcal{O}(1)\).+--   Empty tree.+empty :: RadixTree a+empty = empty0++{-# INLINE singleton #-}+-- | \(\mathcal{O}(x)\).+--   Tree with a single entry.+singleton :: Feed -> a -> RadixTree a+singleton = singleton0++++-- | \(\mathcal{O}(1)\texttt{+}, \mathcal{O}(n)\).+--   Create a lazy 'Lazy.Patricia' tree from a strict one.+--+--   The resulting tree does not share its data representation with the original.+toLazy :: StrictRadixTree a -> LazyRadixTree a+toLazy = toLazy0++++-- | \(\mathcal{O}(1)\).+--   Check if the tree is empty.+null :: RadixTree a -> Bool+null = null0++-- | \(\mathcal{O}(n)\).+--   Calculate the number of elements stored in the tree.+--   The returned number is guaranteed to be non-negative.+size :: RadixTree a -> Int+size = size0++++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+map :: (a -> b) -> RadixTree a -> RadixTree b+map = map0++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+map' :: (a -> b) -> RadixTree a -> RadixTree b+map' = map0'++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+mapWithKey :: (Build -> a -> b) -> RadixTree a -> RadixTree b+mapWithKey = mapWithKey0++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree.+mapWithKey' :: (Build -> a -> b) -> RadixTree a -> RadixTree b+mapWithKey' = mapWithKey0'++++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldl :: (b -> a -> b) -> b -> RadixTree a -> b+foldl = Data.RadixNTree.Word8.Strict.foldl0++-- | \(\mathcal{O}(n_R)\).+--   Fold the tree left-to-right.+foldlWithKey :: (b -> Build -> a -> b) -> b -> RadixTree a -> b+foldlWithKey = foldlWithKey0++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldl' :: (b -> a -> b) -> b -> RadixTree a -> b+foldl' = foldl0'++-- | \(\mathcal{O}(n)\).+--   Fold the tree left-to-right with a strict accumulator.+foldlWithKey' :: (b -> Build -> a -> b) -> b -> RadixTree a -> b+foldlWithKey' = foldlWithKey0'++++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldr :: (a -> b -> b) -> b -> RadixTree a -> b+foldr = Data.RadixNTree.Word8.Strict.foldr0++-- | \(\mathcal{O}(n_L)\).+--   Fold the tree right-to-left.+foldrWithKey :: (Build -> a -> b -> b) -> b -> RadixTree a -> b+foldrWithKey = foldrWithKey0++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldr' :: (a -> b -> b) -> b -> RadixTree a -> b+foldr' = foldr0'++-- | \(\mathcal{O}(n)\).+--   Fold the tree right-to-left with a strict accumulator.+foldrWithKey' :: (Build -> a -> b -> b) -> b -> RadixTree a -> b+foldrWithKey' = foldrWithKey0'++++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMap :: Monoid m => (a -> m) -> RadixTree a -> m+foldMap = foldMap0++-- | \(\mathcal{O}(n_M)\).+--   Map each element in the tree to a monoid and combine the results.+foldMapWithKey :: Monoid m => (Build -> a -> m) -> RadixTree a -> m+foldMapWithKey = foldMapWithKey0++++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverse :: Applicative f => (a -> f b) -> RadixTree a -> f (RadixTree b)+traverse = traverse0++-- | \(\mathcal{O}(n)\).+--   Map each element in the tree to an action, evaluate these actions+--   left-to-right and collect the results.+traverseWithKey+  :: Applicative f => (Build -> a -> f b) -> RadixTree a -> f (RadixTree b)+traverseWithKey = traverseWithKey0++++-- | \(\mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filter :: (a -> Bool) -> RadixTree a -> RadixTree a+filter = filter0++-- | \(\mathcal{O}(n)\).+--   Filter values that satisfy the value predicate.+filterWithKey :: (Build -> a -> Bool) -> RadixTree a -> RadixTree a+filterWithKey = filterWithKey0++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create one out of 'Just' values.+--+--   The 'Maybe' is evaluated to WHNF.+mapMaybe :: (a -> Maybe b) -> RadixTree a -> RadixTree b+mapMaybe = mapMaybe0++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create one out of 'Just' values.+--+--   The 'Maybe' is evaluated to WHNF.+mapMaybeWithKey :: (Build -> a -> Maybe b) -> RadixTree a -> RadixTree b+mapMaybeWithKey = mapMaybeWithKey0+++-- | \(\mathcal{O}(n)\).+--   Split the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partition :: (a -> Bool) -> RadixTree a -> Split a a+partition = partition0++-- | \(\mathcal{O}(n)\).+--   Split the tree into two, such that values that satisfy the predicate+--   are on the left and values that do not are on the right.+partitionWithKey :: (Build -> a -> Bool) -> RadixTree a -> Split a a+partitionWithKey = partitionWithKey0++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+--+--   The 'Either' is evaluated to WHNF.+mapEither :: (a -> Either b c) -> RadixTree a -> Split b c+mapEither = mapEither0++-- | \(\mathcal{O}(n)\).+--   Apply a function to every value in the tree and create two trees,+--   one out of 'Left' results and one out of 'Right' ones.+--+--   The 'Either' is evaluated to WHNF.+mapEitherWithKey :: (Build -> a -> Either b c) -> RadixTree a -> Split b c+mapEitherWithKey = mapEitherWithKey0++++{-# INLINE lookup #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the value at a key in the tree.+lookup :: Feed -> RadixTree a -> Maybe a+lookup = lookup0++{-# INLINE find #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the value at a key in the tree, falling back to the given default value+--   if it does not exist.+find :: a -> Feed -> RadixTree a -> a+find = find0++{-# INLINE member #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Check whether the value exists at a key in the tree.+member :: Feed -> RadixTree a -> Bool+member = member0++{-# INLINE subtree #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the part of the tree below the given prefix.+subtree :: Feed -> RadixTree a -> RadixTree a+subtree = subtree0++{-# INLINE prefix #-}+-- | \(\mathcal{O}(x)\).+--   Prefix the root of the tree with the given key.+prefix :: Feed -> RadixTree a -> RadixTree a+prefix = prefix0+++-- | \(\mathcal{O}(1)\).+--   Make a cursor that points to the root of the tree.+cursor :: RadixTree a -> Cursor a+cursor = cursor0++{-# INLINE move #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Move the cursor down by the extent of the given key.+move :: Feed -> Cursor a -> Cursor a+move = move0++++{-# INLINE insert #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, it is replaced.+insert :: Feed -> a -> RadixTree a -> RadixTree a+insert = insert0++{-# INLINE insertWith #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, the function is used instead.+insertWith :: (a -> a) -> Feed -> a -> RadixTree a -> RadixTree a+insertWith = insertWith0++{-# INLINE insertWith' #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Insert a new value in the tree at the given key.+--   If a value already exists at that key, the function is used instead.+--+--   New value is evaluated to WHNF.+insertWith' :: (a -> a) -> Feed -> a -> RadixTree a -> RadixTree a+insertWith' = insertWith0'+++{-# INLINE adjust #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Apply a function to a value in the tree at the given key.+adjust :: (a -> a) -> Feed -> RadixTree a -> RadixTree a+adjust = adjust0++{-# INLINE adjust' #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Apply a function to a value in the tree at the given key.+--+--   New value is evaluated to WHNF.+adjust' :: (a -> a) -> Feed -> RadixTree a -> RadixTree a+adjust' = adjust0'+++{-# INLINE delete #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Delete a value in the tree at the given key.+delete :: Feed -> RadixTree a -> RadixTree a+delete = delete0++{-# INLINE prune #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Delete values in the tree below the given key.+prune :: Openness -> Feed -> RadixTree a -> RadixTree a+prune = prune0+++{-# INLINE update #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Update or delete a value in the tree at the given key.+--+--   The 'Maybe' is evaluated to WHNF.+update :: (a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a+update = update0+++{-# INLINE alter #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Insert, update or delete a value in the tree at the given key.+--+--   The resulting 'Maybe' is evaluated to WHNF.+alter :: (Maybe a -> Maybe a) -> Feed -> RadixTree a -> RadixTree a+alter = alter0+++{-# INLINE shape #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Update the part of the tree at the given prefix.+--+--   The resulting 'RadixTree' is evaluated to WHNF.+shape :: (RadixTree a -> RadixTree a) -> Feed -> RadixTree a -> RadixTree a+shape = shape0+++{-# INLINE splitLookup #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Split the tree into two, such that+--   values with keys smaller than the given one are on the left,+--   values with keys greater than the given one are on the right,+--   and the value at the given key is returned separately.+splitLookup :: Feed -> RadixTree a -> SplitLookup a a a+splitLookup = splitLookup0++++{-# INLINE lookupL #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up a value at a largest key smaller than (or equal to) the given key.+lookupL :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)+lookupL = lookupL0+++{-# INLINE lookupR #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Look up a value at a smallest key greater than (or equal to) the given key.+lookupR :: Openness -> Feed -> RadixTree a -> Maybe (Lookup a)+lookupR = lookupR0++++{-# INLINE adjustL #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+adjustL :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustL = adjustL0++{-# INLINE adjustL' #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+--+--   New value is evaluated to WHNF.+adjustL' :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustL' = adjustL0'++{-# INLINE adjustLWithKey #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+adjustLWithKey :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustLWithKey = adjustLWithKey0++{-# INLINE adjustLWithKey' #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Apply a function to every value for which the key is smaller than+--   (or equal to) the given one.+--+--   New value is evaluated to WHNF.+adjustLWithKey' :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustLWithKey' = adjustLWithKey0'++++{-# INLINE adjustR #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+adjustR :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustR = adjustR0++{-# INLINE adjustR' #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+--+--   New value is evaluated to WHNF.+adjustR' :: (a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustR' = adjustR0'++{-# INLINE adjustRWithKey #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+adjustRWithKey :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustRWithKey = adjustRWithKey0++{-# INLINE adjustRWithKey' #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Apply a function to every value for which the key is greater than+--   (or equal to) the given one.+--+--   New value is evaluated to WHNF.+adjustRWithKey' :: (Build -> a -> a) -> Openness -> Feed -> RadixTree a -> RadixTree a+adjustRWithKey' = adjustRWithKey0'++++{-# INLINE updateL #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Update every value for which the key is smaller than (or equal to) the given one.+updateL :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateL = updateL0++{-# INLINE updateLWithKey #-}+-- | \(\mathcal{O}(\min(x,k) + n_L)\).+--   Update every value for which the key is smaller than (or equal to) the given one.+--+--   The 'Maybe' is evaluated to WHNF.+updateLWithKey :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateLWithKey = updateLWithKey0++{-# INLINE updateR #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Update every value for which the key is greater than (or equal to) the given one.+updateR :: (a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateR = updateR0++{-# INLINE updateRWithKey #-}+-- | \(\mathcal{O}(\min(x,k) + n_R)\).+--   Update every value for which the key is greater than (or equal to) the given one.+--+--   The 'Maybe' is evaluated to WHNF.+updateRWithKey :: (Build -> a -> Maybe a) -> Openness -> Feed -> RadixTree a -> RadixTree a+updateRWithKey = updateRWithKey0++++{-# INLINE takeL #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Take values for which keys are smaller than (or equal to) the given one.+takeL :: Openness -> Feed -> RadixTree a -> RadixTree a+takeL = takeL0++{-# INLINE takeR #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Take values for which keys are greater than (or equal to) the given one.+takeR :: Openness -> Feed -> RadixTree a -> RadixTree a+takeR = takeR0++++{-# INLINE splitL #-}+-- | \(\mathcal{O}(\min(x,k))\).+--   Split the tree into two, such that+--   values with keys smaller than (or equal to) the given one are on the left,+--   and the rest are on the right.+splitL :: Openness -> Feed -> RadixTree a -> Split a a+splitL = splitL0++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+lookupMin :: RadixTree a -> Maybe a+lookupMin = lookupMin0++-- | \(\mathcal{O}(k)\).+--   Look up a value at the leftmost key in the tree.+lookupMinWithKey :: RadixTree a -> Maybe (Lookup a)+lookupMinWithKey = lookupMinWithKey0++-- | \(\mathcal{O}(k)\).+--   Delete a value at the leftmost key in the tree.+deleteMin :: RadixTree a -> RadixTree a+deleteMin = deleteMin0++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+adjustMin :: (a -> a) -> RadixTree a -> RadixTree a+adjustMin = adjustMin0++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+adjustMinWithKey :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMinWithKey = adjustMinWithKey0++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMin' :: (a -> a) -> RadixTree a -> RadixTree a+adjustMin' = adjustMin0'++-- | \(\mathcal{O}(k)\).+--   Update a value at the leftmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMinWithKey' :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMinWithKey' = adjustMinWithKey0'++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+updateMin :: (a -> Maybe a) -> RadixTree a -> RadixTree a+updateMin = updateMin0++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the leftmost key in the tree.+updateMinWithKey :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a+updateMinWithKey = updateMinWithKey0++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the leftmost value and return it alongside the tree without it.+minView :: RadixTree a -> Maybe (ViewL a)+minView = minView0++++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+lookupMax :: RadixTree a -> Maybe a+lookupMax = lookupMax0++-- | \(\mathcal{O}(k)\).+--   Look up a value at the rightmost key in the tree.+lookupMaxWithKey :: RadixTree a -> Maybe (Lookup a)+lookupMaxWithKey = lookupMaxWithKey0++-- | \(\mathcal{O}(k)\).+--   Delete a value at the rightmost key in the tree.+deleteMax :: RadixTree a -> RadixTree a+deleteMax = deleteMax0++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+adjustMax :: (a -> a) -> RadixTree a -> RadixTree a+adjustMax = adjustMax0++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+adjustMaxWithKey :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMaxWithKey = adjustMaxWithKey0++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMax' :: (a -> a) -> RadixTree a -> RadixTree a+adjustMax' = adjustMax0'++-- | \(\mathcal{O}(k)\).+--   Update a value at the rightmost key in the tree.+--+--   New value is evaluated to WHNF.+adjustMaxWithKey' :: (Build -> a -> a) -> RadixTree a -> RadixTree a+adjustMaxWithKey' = adjustMaxWithKey0'++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+updateMax :: (a -> Maybe a) -> RadixTree a -> RadixTree a+updateMax = updateMax0++-- | \(\mathcal{O}(k)\).+--   Update or delete a value at the rightmost key in the tree.+updateMaxWithKey :: (Build -> a -> Maybe a) -> RadixTree a -> RadixTree a+updateMaxWithKey = updateMaxWithKey0++-- | \(\mathcal{O}(\min(x,k))\).+--   Look up the rightmost value and return it alongside the tree without it.+maxView :: RadixTree a -> Maybe (ViewR a)+maxView = maxView0++++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Unbiased union of two trees.+union :: RadixTree a -> RadixTree a -> RadixTree a+union = union0++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Left-biased union of two trees.+unionL :: RadixTree a -> RadixTree a -> RadixTree a+unionL = unionL0++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Union of two trees with a combining function.+--+--   New values are evaluated to WHNF.+unionWith' :: (a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a+unionWith' = unionWith0'++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Union of two trees with a combining function.+--+--   New values are evaluated to WHNF.+unionWithKey' :: (Build -> a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a+unionWithKey' = unionWithKey0'++++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees.+difference :: RadixTree a -> RadixTree b -> RadixTree a+difference = difference0++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees with a combining function.+--+--   The 'Maybe' is evaluated to WHNF.+differenceWith+  :: (a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a+differenceWith = differenceWith0++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Difference of two trees with a combining function.+--+--   The 'Maybe' is evaluated to WHNF.+differenceWithKey+  :: (Build -> a -> b -> Maybe a) -> RadixTree a -> RadixTree b -> RadixTree a+differenceWithKey = differenceWithKey0++++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Compare two trees with respect to set inclusion,+--   using the given equality function for intersecting keys.+--   If any intersecting keys hold unequal values, the trees are 'Incomparable'.+compare :: (a -> b -> Bool) -> RadixTree a -> RadixTree b -> PartialOrdering+compare = compare0++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Determine whether two trees' key sets are disjoint.+disjoint :: RadixTree a -> RadixTree b -> Bool+disjoint = disjoint0++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Unbiased intersection of two trees.+intersection :: RadixTree a -> RadixTree a -> RadixTree a+intersection = intersection0++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Left-biased intersection of two trees.+intersectionL :: RadixTree a -> RadixTree b -> RadixTree a+intersectionL = intersectionL0++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Intersection of two trees with a combining function.+--+--   New values are evaluated to WHNF.+intersectionWith' :: (a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c+intersectionWith' = intersectionWith0'++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   Intersection of two trees with a combining function.+--+--   New values are evaluated to WHNF.+intersectionWithKey' :: (Build -> a -> b -> c) -> RadixTree a -> RadixTree b -> RadixTree c+intersectionWithKey' = intersectionWithKey0'
+ src/Data/RadixTree/Word8/Strict/Debug.hs view
@@ -0,0 +1,30 @@+{-|+    Safe functions for datatype introspection.+ -}++module Data.RadixTree.Word8.Strict.Debug+  ( -- * Show+    showsTree++    -- * Validate+  , Validity (..)+  , Reason (..)+  , validate+  ) where++import           Data.RadixNTree.Word8.Strict (RadixTree)+import           Data.RadixNTree.Word8.Strict.Debug++++-- | \(\mathcal{O}(n)\).+--   Shows the internal structure of the tree.+showsTree :: (a -> ShowS) -> RadixTree a -> ShowS+showsTree = showsTree0++++-- | \(\mathcal{O}(n)\).+--   Checks whether the tree is well-formed.+validate :: RadixTree a -> Validity+validate = validate0
+ src/Data/RadixTree/Word8/Strict/TH.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE TemplateHaskellQuotes #-}++{-|+    Template Haskell helper functions.+ -}++module Data.RadixTree.Word8.Strict.TH+  ( sequenceCode+  ) where++import           Data.RadixNTree.Word8.Strict.TH++import           Language.Haskell.TH.Syntax++++-- | \(\mathcal{O}(n)\).+--   Evaluate a tree of typed expressions.+sequenceCode :: Quote m => RadixTree (Code m a) -> Code m (RadixTree a)+sequenceCode = sequenceCode0
+ src/Data/RadixTree/Word8/Strict/Unsafe.hs view
@@ -0,0 +1,71 @@+{-# OPTIONS_HADDOCK not-home #-}++{-|+    Data structure internals, helper operations and unsafe functions.++    == Implementation++    The tree is an altered 'Data.Patricia.Word.Strict.Unsafe.Patricia' tree.++    Each 'Tip' in the radix tree represents a continuous non-empty chunk of the key,+    at the end of which there either exists a value or the rest of the key branches.+    The first byte of the chunk corresponds to a 'Key' in a+    'Data.Patricia.Word.Strict.Unsafe.Patricia' tree, hence the definitions of+    'Bin' and 'Nil' remain unchanged.++    The only state the resulting 'Radix1Tree' is unable to represent is the+    value at the root of the tree (for which the key is an empty byte sequence),+    as such that value is prepended with a special 2-tuple named 'RadixTree'.+ -}++module Data.RadixTree.Word8.Strict.Unsafe+  ( RadixTree (..)+  , Radix1Tree (..)++    -- * Bit operations+  , Prefix+  , Key++    -- | === Compare+  , beyond+  , upper+  , lower++    -- | === Create+  , Mask+  , zeroBit+  , mask+  , branchingBit++    -- * Exceptions+  , MalformedTree (..)++    -- * Full-tree+    -- ** Merge+  , merge+  ) where++import           Data.RadixNTree.Word8.Key+import           Data.RadixNTree.Word8.Strict+import           Radix.Exception+import           Radix.Word8.Foundation++++-- | \(\mathcal{O}(n_A k_A + n_B k_B)\).+--   General merge of two trees.+--+--   Resulting 'Maybe's and 'Radix1Tree's in argument functions are evaluated to WHNF.+--+--   This functions inlines when all argument functions are provided.+{-# INLINE merge #-}+merge+  :: (Build -> a -> b -> Maybe c)            -- ^ Single value collision+  -> (Build -> a -> Maybe c)                 -- ^ Single left value+  -> (Build -> Radix1Tree a -> Radix1Tree c) -- ^ Left subtree+  -> (Build -> b -> Maybe c)                 -- ^ Single right value+  -> (Build -> Radix1Tree b -> Radix1Tree c) -- ^ Right subtree+  -> RadixTree a+  -> RadixTree b+  -> RadixTree c+merge = merge0
+ src/Data/Zebra/Word.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE PatternSynonyms #-}++{-|+    @'Zebra'@ is a fully-strict one-dimensional space partitioning tree,+    using 'Data.Word.Word's as keys.++    == Laziness++    Evaluating the root of the tree (i.e. @(_ :: 'Zebra')@) to+    weak head normal form evaluates the entire tree to normal form.++    == Performance++    Each function's time complexity is provided in the documentation.++    \(n\) refers to the total number of space partitions in the tree.+    Parts of the tree are denoted using subscripts: \(n_L\) refers to the left side,+    \(n_R\) to the right side, and \(n_I\) to a range (interval).++    \(W\) is the size of 'Word' in bits, i.e. @'Data.Bits.finiteBitSize' (0 :: 'Word')@.++    == Implementation++    See the implementation section in "Data.Zebra.Word.Unsafe" for the explanation of+    the innerworkings.++    See the implementation section in "Data.Patricia.Word.Strict" for literary references.+ -}++module Data.Zebra.Word+  ( Zebra+  , Color (..)++    -- * Construct+  , pattern Mono++    -- * Single-key+    -- ** Lookup+  , Data.Zebra.Word.Internal.lookup++    -- * Directional+    -- ** Size+    -- | === Left+  , monoL+  , sizeL++    -- | === Right+  , monoR+  , sizeR++    -- ** Lookup+    -- | === Left+  , lookupL+  , findL++    -- | === Right+  , lookupR+  , findR++    -- ** Insert+    -- | === Left+  , fillL++    -- | === Right+  , fillR++    -- ** Fold+    -- | === Left-to-right++    -- | ===== Left+  , foldlL+  , foldlL'++    -- | ===== Right+  , foldlR+  , foldlR'++    -- | === Right-to-left++    -- | ===== Left+  , foldrL+  , foldrL'++    -- | ===== Right+  , foldrR+  , foldrR'++    -- * Range+  , Range (Range)++    -- ** Size+  , monoRange+  , sizeRange++    -- ** Insert+  , fillRange++    -- ** Fold+    -- | === Left-to-right+  , foldlRange+  , foldlRange'++    -- | === Right-to-left+  , foldrRange+  , foldrRange'++    -- * Full tree+    -- ** Size+  , size++    -- ** Fold+    -- | === Left-to-right+  , Data.Zebra.Word.Internal.foldl+  , Data.Zebra.Word.Internal.foldl'++    -- | === Right-to-right+  , Data.Zebra.Word.Internal.foldr+  , Data.Zebra.Word.Internal.foldr'++    -- ** Complement+  , complement++    -- ** Compare+  , PartialOrdering (..)+  , Data.Zebra.Word.Internal.compare++    -- ** Union+  , union++    -- ** Difference+  , difference+  , symmetricDifference++    -- ** Intersection+  , disjoint+  , intersection+  ) where++import           Data.Zebra.Word.Internal+import           Radix.Common
+ src/Data/Zebra/Word/Debug.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE BangPatterns #-}++{-|+    Safe functions for datatype introspection.+ -}++module Data.Zebra.Word.Debug+  ( -- * Show+    showsTree++    -- * Validate+  , Validity (..)+  , Reason (..)+  , validate+  ) where++import           Data.Zebra.Word.Internal+import           Numeric.Long+import           Radix.Word.Foundation+import           Radix.Word.Debug++++-- | \(\mathcal{O}(n)\).+--   Shows the internal structure of the tree.+showsTree :: Zebra -> ShowS+showsTree = go 0+  where+    go i t =+      mappend (replicate i ' ') .+        case t of+          Bin p l r ->+            showString "Bin " . showPrefix p . showChar '\n'+                              . go (i + 2) l . showChar '\n'+                              . go (i + 2) r++          Bla k     -> goTip Black k+          Whi k     -> goTip White k++          Nil c     -> showString "Nil " . showChar (color c)++    goTip c k =+      showString "Tip " . showLongBin k . showString " => " . showChar (color c)++    color Black = 'B'+    color White = 'W'++++-- | Whether the tree is well-formed.+data Validity = Valid+              | Invalid Reason+                deriving Show++-- | Reason for why the tree is considered malformed.+data Reason = -- | Prefix is @0@.+              ZeroPrefix+              -- | Prefix below diverges from the prefix above+            | PrefixBelow Prefix Prefix+              -- | Key diverges the prefix above+            | KeyBelow Prefix Key+              -- | Nil is in the tree.+            | FoundNil+              -- | Tip has a value of zero despite not being the root.+            | ZeroKey+              -- | Key has the same color as the key to the left of it.+            | NoSwitch Color Key+              deriving Show++data Carry = Carry Color+           | Break Reason++-- | \(\mathcal{O}(n)\).+--   Checks whether the tree is well-formed.+validate :: Zebra -> Validity+validate t0 =+  case go0 t0 of+    Carry _ -> Valid+    Break r -> Invalid r+  where+    go0 t =+      case t of+        Bin p l r+          | p == 0    -> Break ZeroPrefix+          | otherwise ->+              case go L p l Nothing of+                Carry cR -> go R p r (Just cR)+                err      -> err++        Bla _ -> Carry Black+        Whi _ -> Carry White++        Nil _ -> Break FoundNil++    go s q x cL =+      case x of+        Bin p l r+          | p == 0                 -> Break ZeroPrefix+          | not $ validBelow q s p -> Break $ PrefixBelow q p+          | otherwise              ->+              case go L p l cL of+                Carry cR -> go R p r (Just cR)+                err      -> err++        Bla k -> goTip s q k cL Black+        Whi k -> goTip s q k cL White++        Nil _ -> Break FoundNil++    goTip s q k cL c+      | k == 0                 = Break ZeroKey+      | not $ validBelow q s k = Break $ KeyBelow q k+      | Just x <- cL, x == c   = Break $ NoSwitch c k+      | otherwise              = Carry c
+ src/Data/Zebra/Word/Internal.hs view
@@ -0,0 +1,2906 @@+{-# LANGUAGE BangPatterns+           , PatternSynonyms+           , ViewPatterns+           , UnboxedTuples+           , UnboxedSums #-}++module Data.Zebra.Word.Internal+  ( Color (..)+  , Zebra (Mono, ..)++  , Data.Zebra.Word.Internal.lookup+  , lookupL+  , findL+  , lookupR+  , findR++  , Range (..)++  , monoL+  , monoR+  , monoRange++  , unsafeMonoRange++  , size++  , sizeL+  , sizeR+  , sizeRange++  , unsafeSize+  , unsafeSizeL+  , unsafeSizeR+  , unsafeSizeRange++  , fillL+  , fillR+  , fillRange++  , unsafeFillL+  , unsafeFillRange++  , Data.Zebra.Word.Internal.foldl+  , foldlL+  , foldlR+  , foldlRange+  , unsafeFoldlRange++  , Data.Zebra.Word.Internal.foldr+  , foldrL+  , foldrR+  , foldrRange+  , unsafeFoldrRange++  , Data.Zebra.Word.Internal.foldl'+  , foldlL'+  , foldlR'+  , foldlRange'+  , unsafeFoldlRange'++  , Data.Zebra.Word.Internal.foldr'+  , foldrL'+  , foldrR'+  , foldrRange'+  , unsafeFoldrRange'++  , Data.Zebra.Word.Internal.complement++  , union+  , disjoint+  , intersection++  , difference+  , symmetricDifference++  , Data.Zebra.Word.Internal.compare+  ) where++import           Radix.Common (PartialOrdering (..), order)+import           Radix.Word.Common+import           Radix.Word.Foundation++import           Data.Bits+import           Numeric.Natural++++-- | Space partition colors.+data Color = Black+           | White+             deriving (Show, Eq)++invert :: Color -> (# Color #)+invert Black = (# White #)+invert White = (# Black #)++++-- | Fully-strict one-dimensional space partitioning tree.+data Zebra = Bin+               {-# UNPACK #-} !Prefix+               !Zebra                 -- ^ Masked bit is @0@.+               !Zebra                 -- ^ Masked bit is not @0@.++           | Bla+               -- | Invariant: can only be @0@ as the root of the tree.+               {-# UNPACK #-} !Key++           | Whi+               -- | Invariant: can only be @0@ as the root of the tree.+               {-# UNPACK #-} !Key++           | Nil                     -- ^ Invariant: unreachable state.+               {-# UNPACK #-} !Color++-- | Tree is represented as a list of closed intervals of all 'White' keys.+instance Show Zebra where+  showsPrec _ =+    let f (UnsafeRange kL kR) c z =+          case c of+            Black -> z+            White -> (kL, kR) : z++    in showList . Data.Zebra.Word.Internal.foldr f []++instance Eq Zebra where+  (==) = go+    where+      go l r =+        case l of+          Bin p xl xr ->+            case r of+              Bin q yl yr -> p == q && go xl yl && go xr yr+              _           -> False++          Bla kA ->+            case r of+              Bla kB -> kA == kB+              _      -> False++          Whi kA ->+            case r of+              Whi kB -> kA == kB+              _      -> False++          Nil _ -> False++++-- | \(\mathcal{O}(1)\).+--   All keys are the same color.+pattern Mono :: Color -> Zebra+pattern Mono c <- ( ( \z -> case z of+                              Bla 0 -> Just Black+                              Whi 0 -> Just White+                              _     -> Nothing+                    )+                      -> Just c+                  )+  where+    Mono Black = Bla 0+    Mono White = Whi 0++++{-# INLINE join #-}+-- | Knowing that the prefices of two non-'Nil' trees disagree, construct a 'Bin'.+join :: Prefix -> Zebra -> Prefix -> Zebra -> Zebra+join p0 t0 p1 t1 =+  let m = branchingBit p0 p1++      p = mask p0 m .|. m++  in if zeroBit p0 m+       then Bin p t0 t1+       else Bin p t1 t0++{-# INLINE rebin #-}+-- | Reconstruct a 'Bin' knowing that either of the sides may now be a 'Nil'.+rebin :: Prefix -> Zebra -> Zebra -> Zebra+rebin p l r =+  case l of+    Nil _ -> r+    _     ->+      case r of+        Nil _ -> l+        _     -> Bin p l r++{-# INLINE rebinL #-}+-- | Reconstruct a 'Bin' knowing that the left side may now be a 'Nil'.+rebinL :: Prefix -> Zebra -> Zebra -> Zebra+rebinL p l r =+  case l of+    Nil _ -> r+    _     -> Bin p l r+++{-# INLINE rebinR #-}+-- | Reconstruct a 'Bin' knowing that the right side may now be a 'Nil'.+rebinR :: Prefix -> Zebra -> Zebra -> Zebra+rebinR p l r =+  case r of+    Nil _ -> l+    _     -> Bin p l r++{-# INLINE tip #-}+tip :: Key -> Color -> Zebra+tip k Black = Bla k+tip k White = Whi k++++-- | \(\mathcal{O}(\min(n,W))\).+--   Check whether all keys smaller than or equal to the given key are of the same color.+monoL :: Word -> Zebra -> Maybe Color+monoL !w = go+  where+    go t =+      case t of+        Bin p l _ ->+          if w < p+            then if w >= lower p+                   then go l+                   else let !(# cR #) = colorL l+                            !(# cL #) = invert cR+                        in Just cL++            else Nothing++        Bla k       -> goTip Black k+        Whi k       -> goTip White k+        Nil _       -> Nothing++    goTip c k+      | k == 0    = Just c+      | w < k     = let !(# x #) = invert c+                    in Just x+      | otherwise = Nothing++++-- | \(\mathcal{O}(\min(n,W))\).+--   Check whether all keys greater than or equal to the given key are of the same color.+monoR :: Word -> Zebra -> Maybe Color+monoR !w = go+  where+    go t =+      case t of+        Bin p _ r ->+          if w < p+            then Nothing+            else if w <= upper p+                   then go r+                   else let !(# cR #) = colorR r+                        in Just cR++        Bla k       -> goTip Black k+        Whi k       -> goTip White k+        Nil _       -> Nothing++    goTip c k+      | w >= k    = Just c+      | otherwise = Nothing++++-- | \(\mathcal{O}(\min(n,W))\).+--   Check whether all keys in the range are of the same color.+monoRange :: Range -> Zebra -> Maybe Color+monoRange (UnsafeRange kL kR)+  | kR == maxBound = monoR kL+  | otherwise      = unsafeMonoRange kL (kR + 1)++-- | \(\mathcal{O}(\min(n,W))\).+--   Check whether all keys in the range are of the same color.+--+--    \(k_R\) __must__ be greater than \(k_L\).+unsafeMonoRange+  :: Word  -- ^ \(k_L\)+  -> Word  -- ^ \(k_R\)+  -> Zebra+  -> Maybe Color+unsafeMonoRange !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> let !mcL = monoR wL l+                                      !mcR = monoL wR r++                                  in if mcL == mcR+                                       then mcL+                                       else Nothing++            LT | pM <= upper p -> go r+               | p >= lower pM -> if wL >= p+                                    then monoR wL r+                                    else Nothing++               | otherwise     -> let !(# cR #) = colorR r+                                  in Just cR++            GT | p <= upper pM -> if wR <= p+                                    then monoL wR l+                                    else Nothing++               | pM >= lower p -> go l+               | otherwise     -> let !(# cR #) = colorL l+                                      !(# cL #) = invert cR+                                  in Just cL++        Bla k       -> goTip Black k+        Whi k       -> goTip White k+        Nil _       -> Nothing++    goTip c k+      | wL >= k   = Just c+      | wR <= k   = let !(# x #) = invert c+                    in Just x+      | otherwise = Nothing++++-- | \(\mathcal{O}(n)\).+--   Calculate the number of keys of the given color.+--   The returned number is guaranteed to be in the \([0, 2^W]\) interval.+size :: Color -> Zebra -> Natural+size !x t =+  case t of+    Bla 0 -> goZero Black+    Whi 0 -> goZero White+    _     -> fromIntegral $ unsafeSize x t+  where+    goZero c+      | x == c    = fromIntegral (maxBound :: Word) + 1+      | otherwise = 0++-- | \(\mathcal{O}(n)\).+--   Calculate the number of keys of the given color.+--+--   The tree __must not__ be 'Mono'.+unsafeSize :: Color -> Zebra -> Word+unsafeSize !x = size_ x 0 0++size_ :: Color -> Word -> Word -> Zebra -> Word+size_ !x = go+  where+    go !kL !kR t =+      case t of+        Bin p l r ->+          let !nL = go kL p l+              !nR = go p kR r++          in nL + nR++        Bla k -> goTip kL kR k Black+        Whi k -> goTip kL kR k White++        Nil _ -> 0++    goTip !kL !kR k c+      | x == c    = kR - k+      | otherwise = k - kL++++-- | \(\mathcal{O}(\min(n,W) + n_L)\).+--   Calculate the number of keys of the given color that are smaller than+--   or equal to the given key.+--   The returned number is guaranteed to be in the \([0, 2^W]\) interval.+sizeL :: Color -> Word -> Zebra -> Natural+sizeL x w+  | w == maxBound = size x+  | otherwise     = fromIntegral . unsafeSizeL x (w + 1)++-- | \(\mathcal{O}(\min(n,W) + n_L)\).+--   Calculate the number of keys of the given color that are smaller than the given key.+--+--   The given key __must not__ be equal to @'Data.Bits.maxBound'@.+unsafeSizeL :: Color -> Word -> Zebra -> Word+unsafeSizeL x w = sizeL_ x 0 w++sizeL_ :: Color -> Word -> Word -> Zebra -> Word+sizeL_ !x !kL0 !w = go kL0+  where+    go !kL t =+      case t of+        Bin p l r ->+          if w < p+            then go kL l+            else+              let !nL = size_ x kL p l+                  !nR = go p r++              in nL + nR++        Bla k -> goTip kL k Black+        Whi k -> goTip kL k White++        Nil _ -> 0++    goTip !kL k c+      | x == c    = if w > k+                      then w - k+                      else 0++      | otherwise = let i | w > k     = k+                          | otherwise = w++                    in i - kL++++-- | \(\mathcal{O}(\min(n,W) + n_R)\).+--   Calculate the number of keys of the given color that are greater than+--   or equal to the given key.+--   The returned number is guaranteed to be in the \([0, 2^W]\) interval.+sizeR :: Color -> Word -> Zebra -> Natural+sizeR x w+  | w == 0    = size x+  | otherwise = fromIntegral . unsafeSizeR x w++-- | \(\mathcal{O}(\min(n,W) + n_R)\).+--   Calculate the number of keys of the given color that are greater than+--   or equal to the given key.+--+--   The given key __must not__ be @0@.+unsafeSizeR :: Color -> Word -> Zebra -> Word+unsafeSizeR x w = sizeR_ x w 0++sizeR_ :: Color -> Word -> Word -> Zebra -> Word+sizeR_ !x !w = go+  where+    go !kR t =+      case t of+        Bin p l r ->+          if w < p+            then let !nL = go p l+                     !nR = size_ x p kR r++                 in nL + nR++            else go kR r++        Bla k -> goTip kR k Black+        Whi k -> goTip kR k White++        Nil _ -> 0++    goTip kR k c+      | x == c    = kR - if w > k+                           then w+                           else k++      | otherwise = if w < k+                      then k - w+                      else 0++++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Calculate the number of keys of the given color in the range.+sizeRange :: Color -> Range -> Zebra -> Natural+sizeRange x (UnsafeRange kL kR)+  | kR == maxBound = sizeR x kL+  | otherwise      = fromIntegral . unsafeSizeRange x kL (kR + 1)++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Calculate the number of keys of the given color in the \([k_L, k_R)\) interval.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeSizeRange+  :: Color+  -> Word  -- ^ \(k_L\)+  -> Word  -- ^ \(k_R\)+  -> Zebra+  -> Word+unsafeSizeRange !x !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> let !n = sizeR_ x wL p l+                                      !m = sizeL_ x p wR r++                                  in n + m++            LT | pM <= upper p -> go r+               | p >= lower pM -> if wL < p+                                    then let !n = sizeR_ x wL p l+                                             !m = size_ x p wR r++                                         in n + m++                                    else sizeR_ x wL wR r++               | otherwise     -> let !(# cR #) = colorR r+                                  in if cR == x+                                       then wR - wL+                                       else 0++            GT | p <= upper pM -> if wR >= p+                                    then let !n = size_ x wL p l+                                             !m = sizeL_ x p wR r++                                         in n + m++                                    else sizeL_ x wL wR l++               | pM >= lower p -> go l+               | otherwise     -> let !(# cR #) = colorL l+                                  in if cR == x+                                       then 0+                                       else wR - wL++        Bla k -> goTip k Black+        Whi k -> goTip k White++        Nil _ -> 0++    goTip k c+      | x == c    = if wR >= k+                      then wR - if wL > k+                                  then wL+                                  else k+                      else 0++      | otherwise = if wL <= k+                      then let i | wR > k    = k+                                 | otherwise = wR++                           in i - wL++                      else 0++++-- | \(\mathcal{O}(n_R)\).+--   Fold left-to-right over the ranges.+foldl :: (a -> Range -> Color -> a) -> a -> Zebra -> a+foldl f = \z t ->+  case t of+    Bin _ l r -> let !(# w', x', z' #) = foldl_L 0 f z l+                 in foldl_R maxBound f w' x' z' r++    Bla k     -> tipM z k Black+    Whi k     -> tipM z k White+    Nil _     -> z+  where+    tipM z k c+      | k == 0    = let !r = UnsafeRange 0 maxBound+                    in f z r c++      | otherwise = let z' = let !k' = k - 1++                                 !(# x #) = invert c++                             in f z (UnsafeRange 0 k') x++                    in f z' (UnsafeRange k maxBound) c++foldl_L :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> (# Word, Color, a #)+foldl_L !wL f = go+  where+    go z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = go z l+                     in foldl_M f w' x' z' r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# 0, Black, z #)+      where+        goTip k c = (# k, c, if k == 0+                               then z+                               else let !k' = k - 1++                                        !(# x #) = invert c++                                    in f z (UnsafeRange wL k') x+                     #)++foldl_R :: Word -> (a -> Range -> Color -> a) -> Word -> Color -> a -> Zebra -> a+foldl_R !wR f = go+  where+    go !w !x z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = foldl_M f w x z l+                     in go w' x' z' r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c = let z' = let !k' = k - 1+                             in f z (UnsafeRange w k') x++                        !r' = UnsafeRange k wR++                    in f z' r' c++foldl_M :: (a -> Range -> Color -> a) -> Word -> Color -> a -> Zebra -> (# Word, Color, a #)+foldl_M f = go+  where+    go w x z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = go w x z l+                     in go w' x' z' r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# w, x, z #)+      where+        goTip k c = (# k, c, let !k' = k - 1+                             in f z (UnsafeRange w k') x+                     #)++++-- | \(\mathcal{O}(n_R)\).+--   Fold left-to-right over the ranges of all the keys smaller than+--   or equal to the given one.+foldlL :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a+foldlL = foldlL_ 0++foldlL_ :: Word -> Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a+foldlL_ !wL !wR f = go+  where+    go z t =+      case t of+        Bin p l r ->+          if wR < p+            then go z l+            else let !(# w', x', z' #) = foldl_L wL f z l+                 in foldlL_R wR f w' x' z' r++        Bla k     -> tipM k Black+        Whi k     -> tipM k White+        Nil _     -> z+      where+        tipM k c+          | k == 0    = let !r = UnsafeRange wL wR+                        in f z r c++          | otherwise =+              let !(# x #) = invert c+              in if wR < k+                   then f z (UnsafeRange wL wR) x+                   else let z' = let !k' = k - 1+                                 in f z (UnsafeRange wL k') x++                        in f z' (UnsafeRange k wR) c++foldlL_R :: Word -> (a -> Range -> Color -> a) -> Word -> Color -> a -> Zebra -> a+foldlL_R !wR f = go+  where+    go !w !x z t =+      case t of+        Bin p l r ->+          if wR < p+            then go w x z l+            else let !(# w', x', z' #) = foldl_M f w x z l+                 in go w' x' z' r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c+          | wR < k    = let !r = UnsafeRange w wR+                        in f z r x++          | otherwise = let z' = let !k' = k - 1+                                 in f z (UnsafeRange w k') x++                        in f z' (UnsafeRange k wR) c++++-- | \(\mathcal{O}(n_R)\).+--   Fold left-to-right over the ranges of all the keys greater than+--   or equal to the given one.+foldlR :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a+foldlR wL = foldlR_ wL maxBound++foldlR_ :: Word -> Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a+foldlR_ !wL !wR f = go+  where+    go z t =+      case t of+        Bin p l r ->+          if wL < p+            then let !(# w', x', z' #) = foldlR_L wL f z l+                 in foldl_R wR f w' x' z' r++            else go z r++        Bla k     -> tipM k Black+        Whi k     -> tipM k White+        Nil _     -> z+      where+        tipM k c+          | wL >= k   = f z (UnsafeRange wL wR) c+          | otherwise = let !k' = k - 1+                            !(# x #) = invert c++                            z' = f z (UnsafeRange wL k') x++                        in f z' (UnsafeRange k wR) c++foldlR_L :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> (# Word, Color, a #)+foldlR_L !wL f = go+  where+    go z t =+      case t of+        Bin p l r ->+          if wL < p+            then let !(# w', x', z' #) = go z l+                 in foldl_M f w' x' z' r++            else go z r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# 0, Black, z #)+      where+        goTip k c+          | wL >= k   = (# wL, c, z #)++          | otherwise = let !k' = k - 1+                            !(# x #) = invert c++                        in (# k, c, f z (UnsafeRange wL k') x #)++++-- | \(\mathcal{O}(\min(n,W) + n_{I_R})\).+--   Fold left-to-right over the ranges of all the keys in the given range.+foldlRange :: Range -> (a -> Range -> Color -> a) -> a -> Zebra -> a+foldlRange (UnsafeRange wL wR) f z+  | wL == wR  = \t -> let !c = Data.Zebra.Word.Internal.lookup wL t+                      in f z (UnsafeRange wL wR) c++  | otherwise = unsafeFoldlRange wL wR f z++-- | \(\mathcal{O}(n)\).+--   Fold left-to-right over the ranges of all the keys+--   in the \([k_L, k_R)\) interval.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeFoldlRange+  :: Word                       -- ^ \(k_L\)+  -> Word                       -- ^ \(k_R\)+  -> (a -> Range -> Color -> a)+  -> a+  -> Zebra+  -> a+unsafeFoldlRange !wL !wR f = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go z t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> let !(# w', x', z' #) = foldlR_L wL f z l+                                  in foldlL_R wR f w' x' z' r++            LT | pM <= upper p -> go z r+               | p >= lower pM -> if wL < p+                                    then let !(# w', x', z' #) = foldlR_L wL f z l+                                         in foldl_R wR f w' x' z' r++                                    else foldlR_ wL wR f z r++               | otherwise     -> let !(# cR #) = colorR r+                                  in f z (UnsafeRange wL wR) cR++            GT | p <= upper pM -> if wR >= p+                                    then let !(# w', x', z' #) = foldl_L wL f z l+                                         in foldlL_R wR f w' x' z' r++                                    else foldlL_ wL wR f z l++               | pM >= lower p -> go z l+               | otherwise     -> let !(# cR #) = colorL l+                                      !(# cL #) = invert cR++                                  in f z (UnsafeRange wL wR) cL++        Bla k     -> tipM k Black+        Whi k     -> tipM k White+        Nil _     -> z+      where+        tipM k c+          | wL >= k   = f z (UnsafeRange wL wR) c+          | otherwise =+              let !(# x #) = invert c+              in if wR < k+                   then f z (UnsafeRange wL wR) x+                   else let !k' = k - 1++                            z' = f z (UnsafeRange wL k') x++                        in f z' (UnsafeRange k wR) c++++-- | \(\mathcal{O}(n_L)\).+--   Fold right-to-left over the ranges.+foldr :: (Range -> Color -> a -> a) -> a -> Zebra -> a+foldr f = \z t ->+  case t of+    Bin _ l r -> let !(# w', x', z' #) = foldr_R maxBound f z r+                 in foldr_L 0 f w' x' z' l++    Bla k     -> goTip z k Black+    Whi k     -> goTip z k White+    Nil _     -> z+  where+    goTip z k c+      | k == 0    = f (UnsafeRange 0 maxBound) c z++      | otherwise = let !k' = k - 1++                        !(# x #) = invert c++                    in f (UnsafeRange 0 k') x $ f (UnsafeRange k maxBound) c z++foldr_R :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> (# Word, Color, a #)+foldr_R !wR f = go+  where+    go z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = go z r+                     in foldr_M f w' x' z' l++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# 0, Black, z #)+      where+        goTip k c = let !k' = k - 1+                    in (# k', c, f (UnsafeRange k wR) c z #)++foldr_L :: Word -> (Range -> Color -> a -> a) -> Word -> Color -> a -> Zebra -> a+foldr_L !wL f = go+  where+    go !w !x z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = foldr_M f w x z r+                     in go w' x' z' l++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c+          | k == 0    = f (UnsafeRange wL w) c z++          | otherwise = let !k' = k - 1+                        in f (UnsafeRange wL k') x $ f (UnsafeRange k w) c z++foldr_M+  :: (Range -> Color -> a -> a) -> Word -> Color -> a -> Zebra -> (# Word, Color, a #)+foldr_M f = go+  where+    go w x z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = go w x z r+                     in go w' x' z' l++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# w, x, z #)+      where+        goTip k c = let !k' = k - 1+                    in (# k', c, f (UnsafeRange k w) c z #)++++-- | \(\mathcal{O}(n_L)\).+--   Fold right-to-left over the ranges of all the keys greater than+--   or equal to the given one.+foldrR :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a+foldrR wL = foldrR_ wL maxBound++foldrR_ :: Word -> Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a+foldrR_ !wL !wR f = go+  where+    go z t =+      case t of+        Bin p l r ->+          if wL < p+            then let !(# w', x', z' #) = foldr_R wR f z r+                 in foldrR_L wL f w' x' z' l++            else go z r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c+          | k == 0    = f (UnsafeRange wL wR) c z++          | wL < k    = let !k' = k - 1++                            !(# x #) = invert c++                        in f (UnsafeRange wL k') x $ f (UnsafeRange k wR) c z++          | otherwise = f (UnsafeRange wL wR) c z++foldrR_L :: Word -> (Range -> Color -> a -> a) -> Word -> Color -> a -> Zebra -> a+foldrR_L !wL f = go+  where+    go !w !x z t =+      case t of+        Bin p l r ->+          if wL < p+            then let !(# w', x', z' #) = foldr_M f w x z r+                 in go w' x' z' l++            else go w x z r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c+          | wL < k    = let !k' = k - 1+                        in f (UnsafeRange wL k') x $ f (UnsafeRange k w) c z++          | otherwise = f (UnsafeRange wL w) c z++++-- | \(\mathcal{O}(n_L)\).+--   Fold right-to-left over the ranges of all the keys smaller than+--   or equal to the given one.+foldrL :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a+foldrL = foldrL_ 0++foldrL_ :: Word -> Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a+foldrL_ !wL !wR f = go+  where+    go z t =+      case t of+        Bin p l r ->+          if wR < p+            then go z l+            else let !(# w', x', z' #) = foldrL_R wR f z r+                 in foldr_L wL f w' x' z' l++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c+          | k == 0    = f (UnsafeRange wL wR) c z++          | wR >= k   = let !k' = k - 1++                            !(# x #) = invert c++                        in f (UnsafeRange wL k') x $ f (UnsafeRange k wR) c z++          | otherwise = let !(# x #) = invert c+                        in f (UnsafeRange wL wR) x z++foldrL_R :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> (# Word, Color, a #)+foldrL_R !wR f = go+  where+    go z t =+      case t of+        Bin p l r ->+          if wR < p+            then go z l+            else let !(# w', x', z' #) = go z r+                 in foldr_M f w' x' z' l++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# 0, Black, z #)+      where+        goTip k c+          | wR >= k   = let !k' = k - 1+                        in (# k', c, f (UnsafeRange k wR) c z #)++          | otherwise = (# wR, c, z #)++++-- | \(\mathcal{O}(\min(n,W) + n_{I_L})\).+--   Fold right-to-left over the ranges of all the keys in the given range.+foldrRange :: Range -> (Range -> Color -> a -> a) -> a -> Zebra -> a+foldrRange (UnsafeRange wL wR) f z+  | wL == wR  = \t -> let !c = Data.Zebra.Word.Internal.lookup wL t+                      in f (UnsafeRange wL wR) c z++  | otherwise = unsafeFoldrRange wL wR f z++-- | \(\mathcal{O}(\min(n,W) + n_{I_L})\).+--   Fold right-to-left over the ranges of all the keys+--   in the \([k_L, k_R)\) interval.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeFoldrRange+  :: Word                       -- ^ \(k_L\)+  -> Word                       -- ^ \(k_R\)+  -> (Range -> Color -> a -> a)+  -> a+  -> Zebra+  -> a+unsafeFoldrRange !wL !wR f = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go z t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> let !(# w', x', z' #) = foldrL_R wR f z r+                                  in foldrR_L wL f w' x' z' l++            LT | pM <= upper p -> go z r+               | p >= lower pM -> if wL < p+                                    then let !(# w', x', z' #) = foldrL_R wR f z r+                                         in foldr_L wL f w' x' z' l++                                    else foldrR_ wL wR f z r++               | otherwise     -> let !(# cR #) = colorR r+                                  in f (UnsafeRange wL wR) cR z++            GT | p <= upper pM -> if wR >= p+                                    then let !(# w', x', z' #) = foldr_R wR f z r+                                         in foldrR_L wL f w' x' z' l++                                    else foldrL_ wL wR f z l++               | pM >= lower p -> go z l++               | otherwise     -> let !(# cR #) = colorL l+                                      !(# cL #) = invert cR++                                  in f (UnsafeRange wL wR) cL z++        Bla k     -> tipM k Black+        Whi k     -> tipM k White+        Nil _     -> z+      where+        tipM k c+          | wL >= k   = f (UnsafeRange wL wR) c z+          | otherwise =+              let !(# x #) = invert c+              in if wR < k+                   then f (UnsafeRange wL wR) x z+                   else let !k' = k - 1+                        in f (UnsafeRange wL k') x $ f (UnsafeRange k wR) c z++++-- | \(\mathcal{O}(n)\).+--   Fold left-to-right over the ranges with a strict accumulator.+foldl' :: (a -> Range -> Color -> a) -> a -> Zebra -> a+foldl' f = \ !z t ->+  case t of+    Bin _ l r -> let !(# w', x', z' #) = foldl'_L 0 f z l+                 in foldl'_R maxBound f w' x' z' r++    Bla k     -> goTip z k Black+    Whi k     -> goTip z k White+    Nil _     -> z+  where+    goTip z k c+      | k == 0    = f z (UnsafeRange 0 maxBound) c++      | otherwise = let !z' = let !k' = k - 1++                                  !(# x #) = invert c++                              in f z (UnsafeRange 0 k') x++                    in f z' (UnsafeRange k maxBound) c++foldl'_L :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> (# Word, Color, a #)+foldl'_L !wL f = go+  where+    go !z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = go z l+                     in foldl'_M f w' x' z' r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# 0, Black, z #)+      where+        goTip k c = let !k' = k - 1++                        !(# x #) = invert c++                    in (# k, c, if k == 0+                                  then z+                                  else f z (UnsafeRange wL k') x #)++foldl'_R :: Word -> (a -> Range -> Color -> a) -> Word -> Color -> a -> Zebra -> a+foldl'_R !wR f = go+  where+    go !w !x !z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = foldl'_M f w x z l+                     in go w' x' z' r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c = let !z' = f z (UnsafeRange w (k - 1)) x+                    in f z' (UnsafeRange k wR) c++foldl'_M+  :: (a -> Range -> Color -> a) -> Word -> Color -> a -> Zebra -> (# Word, Color, a #)+foldl'_M f = go+  where+    go w x !z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = go w x z l+                     in go w' x' z' r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# w, x, z #)+      where+        goTip k c = (# k, c, f z (UnsafeRange w (k - 1)) x #)++++-- | \(\mathcal{O}(n)\).+--   Fold left-to-right over the ranges of all the keys smaller than+--   or equal to the given one.+foldlL' :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a+foldlL' = foldlL'_ 0++foldlL'_ :: Word -> Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a+foldlL'_ !wL !wR f = go+  where+    go !z t =+      case t of+        Bin p l r ->+          if wR < p+            then go z l+            else let !(# w', x', z' #) = foldl'_L wL f z l+                 in foldlL'_R wR f w' x' z' r++        Bla k     -> tipM k Black+        Whi k     -> tipM k White+        Nil _     -> z+      where+        tipM k c+          | k == 0    = f z (UnsafeRange wL wR) c++          | wR < k    = let !(# x #) = invert c+                        in f z (UnsafeRange wL wR) x++          | otherwise = let !z' = let !k' = k - 1++                                      !(# x #) = invert c++                                      in f z (UnsafeRange wL k') x++                        in f z' (UnsafeRange k wR) c++foldlL'_R :: Word -> (a -> Range -> Color -> a) -> Word -> Color -> a -> Zebra -> a+foldlL'_R !wR f = go+  where+    go !w !x !z t =+      case t of+        Bin p l r ->+          if wR < p+            then go w x z l+            else let !(# w', x', z' #) = foldl'_M f w x z l+                 in go w' x' z' r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c+          | wR < k    = f z (UnsafeRange w wR) x+          | otherwise = let z' = f z (UnsafeRange w (k - 1)) x+                        in f z' (UnsafeRange k wR) c++++-- | \(\mathcal{O}(n)\).+--   Fold left-to-right over the ranges of all the keys greater than+--   or equal to the given one.+foldlR' :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a+foldlR' wL = foldlR'_ wL maxBound++foldlR'_ :: Word -> Word -> (a -> Range -> Color -> a) -> a -> Zebra -> a+foldlR'_ !wL !wR f = go+  where+    go !z t =+      case t of+        Bin p l r ->+          if wL < p+            then let !(# w', x', z' #) = foldlR'_L wL f z l+                 in foldl'_R wR f w' x' z' r++            else go z r++        Bla k     -> tipM k Black+        Whi k     -> tipM k White+        Nil _     -> z+      where+        tipM k c+          | wL >= k   = f z (UnsafeRange wL wR) c+          | otherwise = let !z' = let !k' = k - 1++                                      !(# x #) = invert c++                                      in f z (UnsafeRange wL k') x++                        in f z' (UnsafeRange k wR) c++foldlR'_L :: Word -> (a -> Range -> Color -> a) -> a -> Zebra -> (# Word, Color, a #)+foldlR'_L !wL f = go+  where+    go !z t =+      case t of+        Bin p l r ->+          if wL < p+            then let !(# w', x', z' #) = go z l+                 in foldl'_M f w' x' z' r++            else go z r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# 0, Black, z #)+      where+        goTip k c+          | wL >= k   = (# wL, c, z #)+          | otherwise = let !k' = k - 1++                            !(# x #) = invert c++                        in (# k, c, f z (UnsafeRange wL k') x #)++++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Fold left-to-right over the ranges of all the keys in the given range.+foldlRange' :: Range -> (a -> Range -> Color -> a) -> a -> Zebra -> a+foldlRange' (UnsafeRange wL wR) f z+  | wL == wR  = \t -> let !c = Data.Zebra.Word.Internal.lookup wL t+                      in f z (UnsafeRange wL wR) c++  | otherwise = unsafeFoldlRange' wL wR f z++-- | \(\mathcal{O}(n)\).+--   Fold left-to-right over the ranges of all the keys+--   in the \([k_L, k_R)\) interval.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeFoldlRange'+  :: Word                       -- ^ \(k_L\)+  -> Word                       -- ^ \(k_R\)+  -> (a -> Range -> Color -> a)+  -> a+  -> Zebra+  -> a+unsafeFoldlRange' !wL !wR f = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go z t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> let !(# w', x', z' #) = foldlR'_L wL f z l+                                  in foldlL'_R wR f w' x' z' r++            LT | pM <= upper p -> go z r+               | p >= lower pM -> if wL < p+                                    then let !(# w', x', z' #) = foldlR'_L wL f z l+                                         in foldl'_R wR f w' x' z' r++                                    else foldlR'_ wL wR f z r++               | otherwise     -> let !(# cR #) = colorR r+                                  in f z (UnsafeRange wL wR) cR++            GT | p <= upper pM -> if wR >= p+                                    then let !(# w', x', z' #) = foldl'_L wL f z l+                                         in foldlL'_R wR f w' x' z' r++                                    else foldlL'_ wL wR f z l++               | pM >= lower p -> go z l+               | otherwise     -> let !(# cR #) = colorL l+                                      !(# cL #) = invert cR++                                  in f z (UnsafeRange wL wR) cL++        Bla k     -> tipM k Black+        Whi k     -> tipM k White+        Nil _     -> z+      where+        tipM k c+          | wL >= k   = f z (UnsafeRange wL wR) c+          | otherwise =+              let !(# x #) = invert c+              in if wR < k+                   then f z (UnsafeRange wL wR) x+                   else let !k' = k - 1++                            z' = f z (UnsafeRange wL k') x++                        in f z' (UnsafeRange k wR) c++++-- | \(\mathcal{O}(n)\).+--   Fold right-to-left over the ranges.+foldr' :: (Range -> Color -> a -> a) -> a -> Zebra -> a+foldr' f = \ !z t ->+  case t of+    Bin _ l r -> let !(# w', x', z' #) = foldr'_R maxBound f z r+                 in foldr'_L 0 f w' x' z' l++    Bla k     -> goTip z k Black+    Whi k     -> goTip z k White+    Nil _     -> z+  where+    goTip z k c+      | k == 0    = f (UnsafeRange 0 maxBound) c z++      | otherwise = let !k' = k - 1++                        !(# x #) = invert c++                    in f (UnsafeRange 0 k') x $! f (UnsafeRange k maxBound) c z++foldr'_R :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> (# Word, Color, a #)+foldr'_R !wR f = go+  where+    go !z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = go z r+                     in foldr'_M f w' x' z' l++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# 0, Black, z #)+      where+        goTip k c = let !k' = k - 1+                    in (# k', c, f (UnsafeRange k wR) c z #)++foldr'_L :: Word -> (Range -> Color -> a -> a) -> Word -> Color -> a -> Zebra -> a+foldr'_L !wL f = go+  where+    go !w !x !z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = foldr'_M f w x z r+                     in go w' x' z' l++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c+          | k == 0    = f (UnsafeRange wL w) c z++          | otherwise = let !k' = k - 1+                        in f (UnsafeRange wL k') x $! f (UnsafeRange k w) c z++foldr'_M+  :: (Range -> Color -> a -> a) -> Word -> Color -> a -> Zebra -> (# Word, Color, a #)+foldr'_M f = go+  where+    go w x !z t =+      case t of+        Bin _ l r -> let !(# w', x', z' #) = go w x z r+                     in go w' x' z' l++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# w, x, z #)+      where+        goTip k c = let !k' = k - 1+                    in (# k', c, f (UnsafeRange k w) c z #)++++-- | \(\mathcal{O}(n)\).+--   Fold right-to-left over the ranges of all the keys greater than+--   or equal to the given one.+foldrR' :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a+foldrR' wL = foldrR'_ wL maxBound++foldrR'_ :: Word -> Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a+foldrR'_ !wL !wR f = go+  where+    go !z t =+      case t of+        Bin p l r ->+          if wL < p+            then let !(# w', x', z' #) = foldr'_R wR f z r+                 in foldrR'_L wL f w' x' z' l++            else go z r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c+          | k == 0    = f (UnsafeRange wL wR) c z++          | wL < k    = let !k' = k - 1++                            !(# x #) = invert c++                        in f (UnsafeRange wL k') x $! f (UnsafeRange k wR) c z++          | otherwise = f (UnsafeRange wL wR) c z++foldrR'_L :: Word -> (Range -> Color -> a -> a) -> Word -> Color -> a -> Zebra -> a+foldrR'_L !wL f = go+  where+    go !w !x !z t =+      case t of+        Bin p l r ->+          if wL < p+            then let !(# w', x', z' #) = foldr'_M f w x z r+                 in go w' x' z' l++            else go w x z r++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c+          | wL < k    = let !k' = k - 1+                        in f (UnsafeRange wL k') x $! f (UnsafeRange k w) c z++          | otherwise = f (UnsafeRange wL w) c z++++-- | \(\mathcal{O}(n)\).+--   Fold right-to-left over the ranges of all the keys smaller than+--   or equal to the given one.+foldrL' :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a+foldrL' = foldrL'_ 0++foldrL'_ :: Word -> Word -> (Range -> Color -> a -> a) -> a -> Zebra -> a+foldrL'_ !wL !wR f = go+  where+    go !z t =+      case t of+        Bin p l r ->+          if wR < p+            then go z l+            else let !(# w', x', z' #) = foldrL'_R wR f z r+                 in foldr'_L wL f w' x' z' l++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> z+      where+        goTip k c+          | k == 0    = f (UnsafeRange wL wR) c z++          | wR >= k   = let !k' = k - 1++                            !(# x #) = invert c++                        in f (UnsafeRange wL k') x $! f (UnsafeRange k wR) c z++          | otherwise = let !(# x #) = invert c+                        in f (UnsafeRange wL wR) x z++foldrL'_R :: Word -> (Range -> Color -> a -> a) -> a -> Zebra -> (# Word, Color, a #)+foldrL'_R !wR f = go+  where+    go !z t =+      case t of+        Bin p l r ->+          if wR < p+            then go z l+            else let !(# w', x', z' #) = go z r+                 in foldr'_M f w' x' z' l++        Bla k     -> goTip k Black+        Whi k     -> goTip k White+        Nil _     -> (# 0, Black, z #)+      where+        goTip k c+          | wR >= k   = let !k' = k - 1+                        in (# k', c, f (UnsafeRange k wR) c z #)++          | otherwise = (# wR, c, z #)++++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Fold right-to-left with a strict accumulator over the ranges of all the keys+--   in the given range.+foldrRange' :: Range -> (Range -> Color -> a -> a) -> a -> Zebra -> a+foldrRange' (UnsafeRange wL wR) f !z+  | wL == wR  = \t -> let !c = Data.Zebra.Word.Internal.lookup wL t+                      in f (UnsafeRange wL wR) c z++  | otherwise = unsafeFoldrRange' wL wR f z++-- | \(\mathcal{O}(\min(n,W) + n_I)\).+--   Fold right-to-left with a strict accumulator over the ranges of all the keys+--   in the \([k_L, k_R)\) interval.+--+--   \(k_R\) __must__ be greater than \(k_L\).+unsafeFoldrRange'+  :: Word                       -- ^ \(k_L\)+  -> Word                       -- ^ \(k_R\)+  -> (Range -> Color -> a -> a)+  -> a+  -> Zebra+  -> a+unsafeFoldrRange' !wL !wR f = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    go !z t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> let !(# w', x', z' #) = foldrL'_R wR f z r+                                  in foldrR'_L wL f w' x' z' l++            LT | pM <= upper p -> go z r+               | p >= lower pM -> if wL < p+                                    then let !(# w', x', z' #) = foldrL'_R wR f z r+                                         in foldr'_L wL f w' x' z' l++                                    else foldrR'_ wL wR f z r++               | otherwise     -> let !(# cR #) = colorR r+                                  in f (UnsafeRange wL wR) cR z++            GT | p <= upper pM -> if wR >= p+                                    then let !(# w', x', z' #) = foldr'_R wR f z r+                                         in foldrR'_L wL f w' x' z' l++                                    else foldrL'_ wL wR f z l++               | pM >= lower p -> go z l++               | otherwise     -> let !(# cR #) = colorL l+                                      !(# cL #) = invert cR++                                  in f (UnsafeRange wL wR) cL z++        Bla k     -> tipM k Black+        Whi k     -> tipM k White+        Nil _     -> z+      where+        tipM k c+          | wL >= k   = f (UnsafeRange wL wR) c z+          | otherwise =+              let !(# x #) = invert c+              in if wR < k+                   then f (UnsafeRange wL wR) x z+                   else let !k' = k - 1+                        in f (UnsafeRange wL k') x $! f (UnsafeRange k wR) c z+++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the color of the key.+lookup :: Word -> Zebra -> Color+lookup !w = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go l+                   else let !(# cR #) = colorL l+                            !(# cL #) = invert cR+                        in cL++            else if w <= upper p+                   then go r+                   else let !(# cR #) = colorR r+                        in cR++        Bla k -> goTip k Black+        Whi k -> goTip k White++        Nil _ -> Black++    goTip k c+      | w < k     = let !(# cL #) = invert c+                    in cL+      | otherwise = c++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the key of the given color that is smaller than or equal to the given key.+lookupL :: Color -> Word -> Zebra -> Maybe Word+lookupL !x !w = go (Nil Black)+  where+    go !v t =+      case t of+        Bin p l r+          | w < p     -> go v l+          | otherwise -> go l r++        Bla k -> goTip Black k v+        Whi k -> goTip White k v++        Nil _ -> Nothing++    goTip c k v =+      case w >= k of+        True+          | k == 0    -> if c == x+                           then Just w+                           else Nothing++          | otherwise -> Just $! if c == x+                                   then w+                                   else k - 1+        False+          | c == x    -> case v of+                           Nil _ -> Nothing+                           _     -> let !(# kL #) = keyR v+                                    in Just $! kL - 1++          | otherwise -> Just w++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the key of the given color that is smaller than or equal to the given key,+--   falling back to the default value if no such key exists.+findL+  :: Word -- ^ Default value+  -> Color+  -> Word -- ^ Key+  -> Zebra+  -> Word+findL d !x !w = go (Nil Black)+  where+    go !v t =+      case t of+        Bin p l r+          | w < p     -> go v l+          | otherwise -> go l r++        Bla k -> goTip Black k v+        Whi k -> goTip White k v++        Nil _ -> d++    goTip c k v =+      case w >= k of+        True+          | k == 0    -> if c == x+                           then w+                           else d++          | c == x    -> w+          | otherwise -> k - 1++        False+          | c == x    -> case v of+                           Nil _ -> d+                           _     -> let !(# kL #) = keyR v+                                    in kL - 1+          | otherwise -> w++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the key of the given color that is greater than or equal to the given key.+lookupR :: Color -> Word -> Zebra -> Maybe Word+lookupR !x !w = go (Nil Black)+  where+    go !v t =+      case t of+        Bin p l r+          | w < p     -> go r l+          | otherwise -> go v r++        Bla k -> goTip Black k v+        Whi k -> goTip White k v++        Nil _ -> Nothing++    goTip c k v =+      case w < k of+        True -> Just $! if c == x+                          then k+                          else w+        False+          | c == x    -> Just w+          | otherwise -> case v of+                           Nil _ -> Nothing+                           _     -> let !(# kR #) = keyL v+                                    in Just kR++++-- | \(\mathcal{O}(\min(n,W))\).+--   Look up the key of the given color that is greater than or equal to the given key,+--   falling back to the default value if no such key exists.+findR+  :: Word  -- ^ Default value+  -> Color+  -> Word  -- ^ Key+  -> Zebra+  -> Word+findR d !x !w = go (Nil Black)+  where+    go !v t =+      case t of+        Bin p l r+          | w < p     -> go r l+          | otherwise -> go v r++        Bla k -> goTip Black k v+        Whi k -> goTip White k v++        Nil _ -> d++    goTip c k v =+      case w < k of+        True+          | c == x    -> k+          | otherwise -> w++        False+          | c == x    -> w+          | otherwise -> case v of+                           Nil _ -> d+                           _     -> let !(# kR #) = keyL v+                                    in kR+++++-- | \(\mathcal{O}(\min(n,W))\).+--   Set every key smaller than or equal to the given one to the given color.+fillL :: Word -> Color -> Zebra -> Zebra+fillL w x+  | w == maxBound = \_ -> Mono x+  | otherwise     = unsafeFillL (w + 1) x++-- | \(\mathcal{O}(\min(n,W))\).+--   Set every key smaller than the given one to the given color.+--+--   The given key __must not__ be @0@.+unsafeFillL :: Word -> Color -> Zebra -> Zebra+unsafeFillL w x = \t ->+  case fillL_ w x t of+    Nil _ -> Mono x+    t'    -> t'++fillL_ :: Word -> Color -> Zebra -> Zebra+fillL_ !w !x = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then rebinL p (go l) r+                   else let !(# cR #) = colorL l+                        in if cR == x+                             then let !(# cL #) = invert cR+                                  in join w (tip w cL) p t+                             else t++            else if w <= upper p+                   then go r+                   else let !(# cR #) = colorR r+                        in if cR == x+                             then Nil Black+                             else tip w cR++        Bla k -> goTip Black k t+        Whi k -> goTip White k t++        Nil _ -> t++    goTip c k t+      | w >= k    = if c == x+                      then Nil Black+                      else if w == k+                             then t+                             else tip w c++      | otherwise = if c == x+                      then let !(# cL #) = invert x+                           in join w (tip w cL) k t+                      else t++++-- | \(\mathcal{O}(\min(n,W))\).+--   Set every key greater than or equal to the given one to the given color.+fillR :: Word -> Color -> Zebra -> Zebra+fillR w x = \t ->+  case fillR_ w x t of+    Nil _ -> Mono x+    t'    -> t'++fillR_ :: Word -> Color -> Zebra -> Zebra+fillR_ !w !x = go+  where+    go t =+      case t of+        Bin p l r ->+          if w < p+            then if w >= lower p+                   then go l+                   else let !(# cR #) = colorL l+                        in if cR == x+                             then tip w x+                             else Nil Black++            else if w <= upper p+                   then rebinR p l (go r)+                   else let !(# cR #) = colorR r+                        in if cR == x+                             then t+                             else join w (tip w x) p t++        Bla k -> goTip Black k t+        Whi k -> goTip White k t++        Nil _ -> t++    goTip c k t+      | w <= k    = if c == x+                      then if w == k+                             then t+                             else tip w c++                      else Nil Black++      | otherwise = if c == x+                      then t+                      else if k == 0+                             then tip w x+                             else join w (tip w x) k t++++-- | \(\mathcal{O}(\min(n,W))\).+--   Set every key in the range to the given color.+fillRange :: Range -> Color -> Zebra -> Zebra+fillRange (UnsafeRange wL wR) x+  | wL == 0        = fillL wR x+  | wR == maxBound = fillR wL x+  | otherwise      = unsafeFillRange wL (wR + 1) x++-- | \(\mathcal{O}(\min(n,W) + n_L)\).+--   Set every key in the \([k_L, k_R)\) interval to the given color.+--+--   \(k_L\) __must not__ be @0@. \(k_R\) __must__ be greater than \(k_L\).+unsafeFillRange+  :: Word  -- ^ \(k_L\)+  -> Word  -- ^ \(k_R\)+  -> Color+  -> Zebra+  -> Zebra+unsafeFillRange wL wR x t =+  case fillRange_ x wL wR t of+    Nil _ -> Mono x+    t'    -> t'++fillRange_ :: Color -> Word -> Word -> Zebra -> Zebra+fillRange_ !x !wL !wR = go+  where+    !mM = branchingBit wL wR++    !pM = mask wL mM .|. mM++    binM = let !(# c #) = invert x+           in Bin pM (tip wL x) (tip wR c)++    go t =+      case t of+        Bin p l r ->+          case Prelude.compare p pM of+            EQ                 -> rebin p (fillR_ wL x l) (fillL_ wR x r)++            LT | pM <= upper p -> rebinR p l (go r)+               | p >= lower pM -> let l' = if wL < p+                                             then fillR_ wL x l+                                             else rebinR p l (fillR_ wL x r)++                                      !(# cR #) = colorR r++                                  in if cR == x+                                       then l'+                                       else join p l' pM (tip wR cR)++               | otherwise     ->+                   let !(# cR #) = colorR r+                   in if cR == x+                        then t+                        else join p t pM binM++            GT | p <= upper pM -> let r' = if wR >= p+                                             then fillL_ wR x r+                                             else rebinL p (fillL_ wR x l) r++                                      !(# cR #) = colorL l++                                  in if cR == x+                                       then join pM (tip wL x) p r'+                                       else r'++               | pM >= lower p -> rebinL p (go l) r+               | otherwise     ->+                   let !(# cR #) = colorL l+                   in if cR == x+                        then join p t pM binM+                        else t++        Bla k -> goTip k Black t+        Whi k -> goTip k White t++        Nil _ -> t++    goTip k c t+      | wR < k    = if c == x+                      then join k t pM binM+                      else t++      | k < wL    = if c == x+                      then t+                      else if k == 0+                             then binM+                             else join k t pM binM++      | c == x    = tip wL c+      | otherwise = tip wR c++++colorL :: Zebra -> (# Color #)+colorL t =+  case t of+    Bin _ l _ -> colorL l+    Bla _     -> (# Black #)+    _         -> (# White #)++colorR :: Zebra -> (# Color #)+colorR t =+  case t of+    Bin _ _ r -> colorR r+    Bla _     -> (# Black #)+    _         -> (# White #)+++keyL :: Zebra -> (# Word #)+keyL t =+  case t of+    Bin _ l _ -> keyL l+    Bla k     -> (# k #)+    Whi k     -> (# k #)+    Nil _     -> (# 0 #)++keyR :: Zebra -> (# Word #)+keyR t =+  case t of+    Bin _ _ r -> keyR r+    Bla k     -> (# k #)+    Whi k     -> (# k #)+    Nil _     -> (# 0 #)++++-- | \(\mathcal{O}(n)\).+--   Invert the colors of all keys.+complement :: Zebra -> Zebra+complement t =+  case t of+    Bin p l r -> Bin p (Data.Zebra.Word.Internal.complement l)+                       (Data.Zebra.Word.Internal.complement r)+    Bla k     -> Whi k+    Whi k     -> Bla k+    Nil _     -> t++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Union of two trees over the given color.+union :: Color -> Zebra -> Zebra -> Zebra+union x l r =+  case l of+    Mono c | c == x    -> l+           | otherwise -> r++    _      ->+      case r of+        Mono c | c == x    -> r+               | otherwise -> l++        _      ->+          case anyAny l r of+            Nil _ -> Mono x+            t     -> t+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA -> binAny (# pA, lA, rA #) tA tB++        Bla kA -> tipAny (# kA, Black #) tA tB+        Whi kA -> tipAny (# kA, White #) tA tB++        Nil _ -> tA++    tipAny uA@(# kA, cA #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin uA tA (# pB, lB, rB #) tB++        Bla kB -> goTip kB Black+        Whi kB -> goTip kB White++        Nil _ -> tB+      where+        goTip kB cB+          | cA == cB  = if (cA == x) == (kA < kB)+                          then tA+                          else tB++          | otherwise = if kA == kB || ((cA == x) == (kA < kB))+                          then Nil Black+                          else join kA tA kB tB++    binAny uA tA tB =+      case tB of+        Bin pB lB rB -> binBin uA tA (# pB, lB, rB #) tB++        Bla kB -> tipBin (# kB, Black #) tB uA tA+        Whi kB -> tipBin (# kB, White #) tB uA tA++        Nil _ -> tB++    tipBin uA@(# kA, cA #) tA (# pB, lB, rB #) tB =+      if kA < pB+        then if kA >= lower pB+               then if cA == x+                      then tipAny uA tA lB+                      else rebinL pB (tipAny uA tA lB) rB++               else let !(# cB #) = colorL lB+                    in if cA == cB+                         then if cA == x+                                then tA+                                else tB++                         else if cA == x+                                then Nil Black+                                else join kA tA pB tB++        else if kA <= upper pB+               then if cA == x+                      then rebinR pB lB (tipAny uA tA rB)+                      else tipAny uA tA rB++               else let !(# cB #) = colorR rB+                    in if cA == cB+                         then if cA == x+                                then tB+                                else tA++                         else if cA == x+                                then join kA tA pB tB+                                else Nil Black++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny lA lB) (anyAny rA rB)++        LT | pB <= upper pA -> let !(# cR #) = colorL lB+                               in if cR == x+                                    then rebinR pA lA (binAny uB tB rA)+                                    else binAny uB tB rA++           | pA >= lower pB -> let !(# cL #) = colorR rA+                               in if cL == x+                                    then binAny uA tA lB+                                    else rebinL pB (binAny uA tA lB) rB++           | otherwise      ->+               let !(# cA #) = colorR rA+                   !(# cB #) = colorL lB++               in if cA == cB+                    then if cA == x+                           then tA+                           else tB++                    else if cA == x+                           then Nil Black+                           else join pA tA pB tB++        GT | pA <= upper pB -> let !(# cR #) = colorL lA+                               in if cR == x+                                    then rebinR pB lB (binAny uA tA rB)+                                    else binAny uA tA rB++           | pB >= lower pA -> let !(# cL #) = colorR rB+                               in if cL == x+                                    then binAny uB tB lA+                                    else rebinL pA (binAny uB tB lA) rA++           | otherwise      ->+               let !(# cB #) = colorR rB+                   !(# cA #) = colorL lA++               in if cA == cB+                    then if cA == x+                           then tB+                           else tA++                    else if cA == x+                           then join pA tA pB tB+                           else Nil Black++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Intersection of two trees over the given color.+intersection :: Color -> Zebra -> Zebra -> Zebra+intersection x =+  let !(# c #) = invert x+  in union c++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Determine whether two trees are disjoint over the given color.+disjoint :: Color -> Zebra -> Zebra -> Bool+disjoint x l r =+  case l of+    Mono c -> c /= x+    _      ->+      case r of+        Mono c -> c /= x+        _      -> anyAny l r+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA -> binAny (# pA, lA, rA #) tA tB++        Bla kA -> tipAny (# kA, Black #) tA tB+        Whi kA -> tipAny (# kA, White #) tA tB++        Nil _ -> False++    tipAny uA@(# kA, cA #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin uA tA (# pB, lB, rB #)++        Bla kB -> goTip kB Black+        Whi kB -> goTip kB White++        Nil _ -> False+      where+        goTip kB cB+          | cA == cB  = False+          | otherwise = kA == kB || ((cA == x) == (kA < kB))++    binAny uA tA tB =+      case tB of+        Bin pB lB rB -> binBin uA tA (# pB, lB, rB #) tB++        Bla kB -> tipBin (# kB, Black #) tB uA+        Whi kB -> tipBin (# kB, White #) tB uA++        Nil _ -> False++    tipBin uA@(# kA, cA #) tA (# pB, lB, rB #) =+      if kA < pB+        then if kA >= lower pB+               then cA == x && tipAny uA tA lB++               else let !(# cB #) = colorL lB+                    in cA /= cB && cA == x++        else if kA <= upper pB+               then cA /= x && tipAny uA tA rB++               else let !(# cB #) = colorR rB+                    in cA /= cB && cB == x++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> anyAny lA lB && anyAny rA rB++        LT | pB <= upper pA -> let !(# cR #) = colorL lB+                               in cR /= x && binAny uB tB rA++           | pA >= lower pB -> let !(# cL #) = colorR rA+                               in cL == x && binAny uA tA lB++           | otherwise      ->+               let !(# cA #) = colorR rA+                   !(# cB #) = colorL lB++               in cA /= cB && cA == x++        GT | pA <= upper pB -> let !(# cR #) = colorL lA+                               in cR /= x && binAny uA tA rB++           | pB >= lower pA -> let !(# cL #) = colorR rB+                               in cL == x && binAny uB tB lA++           | otherwise      ->+               let !(# cB #) = colorR rB+                   !(# cA #) = colorL lA++               in cA /= cB && cB == x++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Difference of two trees over the given color.+difference :: Color -> Zebra -> Zebra -> Zebra+difference x l r =+  case l of+    Mono c | c == x    -> Data.Zebra.Word.Internal.complement r+           | otherwise -> l++    _      ->+      case r of+        Mono c | c == x    -> let !(# x' #) = invert x+                              in Mono x'++               | otherwise -> l++        _      ->+          case anyAny L l r of+            Nil _ -> let !(# c #) = invert x+                     in Mono c++            t     -> t+  where+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Bla kA -> tipAny s (# kA, Black #) tA tB+        Whi kA -> tipAny s (# kA, White #) tA tB++        Nil _ -> tA++    tipAny s uA@(# kA, cA #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #) tB++        Bla kB -> goTip kB Black+        Whi kB -> goTip kB White++        Nil _ -> tB+      where+        goTip kB cB =+          case s of+            L -> goTipL kA cA tA kB cB+            R -> goTipL kB cB tB kA cA++        goTipL kL cL tL kR cR =+          case Prelude.compare kL kR of+            EQ -> if cL == cR+                    then Nil Black+                    else tL++            LT -> if cL == cR+                    then if cL == x+                           then let !(# c #) = invert x+                                in join kL tL kR (tip kR c)++                           else Nil Black++                    else if cL == x+                           then tip kR x+                           else tL++            GT -> if cL == cR+                    then if cL == x+                           then Nil Black+                           else join kL tL kR (tip kR x)++                    else if cL == x+                           then tL+                           else tip kR cL++    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Bla kB -> goTip kB Black+        Whi kB -> goTip kB White++        Nil _ -> tB+      where+        goTip kB cB =+          let !(# s' #) = other s+          in tipBin s' (# kB, cB #) tB uA tA++    tipBin s uA@(# kA, cA #) tA (# pB, lB, rB #) tB =+      case s of+        L -> if kA < pB+               then if kA >= lower pB+                      then if cA == x+                             then rebinL pB (tipAny s uA tA lB)+                                            (Data.Zebra.Word.Internal.complement rB)++                             else tipAny s uA tA lB++                      else let !(# cR #) = colorL lB+                           in if cA == cR+                                then if cA == x+                                       then join kA tA+                                                 pB $ Bin pB (Data.Zebra.Word.Internal.complement lB)+                                                             (Data.Zebra.Word.Internal.complement rB)++                                       else Nil Black++                                else if cA == x+                                       then Bin pB (Data.Zebra.Word.Internal.complement lB)+                                                   (Data.Zebra.Word.Internal.complement rB)++                                       else tA++               else if kA <= upper pB+                      then if cA == x+                             then tipAny s uA tA rB+                             else rebinR pB (Data.Zebra.Word.Internal.complement lB)+                                            (tipAny s uA tA rB)++                      else let !(# cL #) = colorR rB+                           in if cA == cL+                                then if cA == x+                                       then Nil Black+                                       else join kA tA+                                                 pB $ Bin pB (Data.Zebra.Word.Internal.complement lB)+                                                             (Data.Zebra.Word.Internal.complement rB)++                                else if cA == x+                                       then tA+                                       else Bin pB (Data.Zebra.Word.Internal.complement lB)+                                                   (Data.Zebra.Word.Internal.complement rB)++        R -> if kA < pB+               then if kA >= lower pB+                      then if cA == x+                             then tipAny s uA tA lB+                             else rebinL pB (tipAny s uA tA lB) rB++                      else let !(# cR #) = colorL lB+                           in if cA == cR+                                then if cA == x+                                       then Nil Black+                                       else join kA (tip kA x) pB tB++                                else if cA == x+                                       then tip kA cR+                                       else tB++               else if kA <= upper pB+                      then if cA == x+                             then rebinR pB lB (tipAny s uA tA rB)+                             else tipAny s uA tA rB++                      else let !(# cL #) = colorR rB+                           in if cA == cL+                                then if cA == x+                                       then let !(# c #) = invert x+                                            in join kA (tip kA c) pB tB+                                       else Nil Black++                                else if cA == x+                                       then tB+                                       else tip kA cL++    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pB (anyAny s lA lB) (anyAny s rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s++                                   !(# cR #) = colorL lB++                               in case s of+                                    L -> if cR == x+                                           then rebinR pA lA (binAny s' uB tB rA)+                                           else binAny s' uB tB rA++                                    R -> if cR == x+                                           then binAny s' uB tB rA+                                           else rebinR pA (Data.Zebra.Word.Internal.complement lA)+                                                          (binAny s' uB tB rA)++           | pA >= lower pB -> let !(# cL #) = colorR rA+                               in case s of+                                    L -> if cL == x+                                           then rebinL pB (binAny s uA tA lB)+                                                  (Data.Zebra.Word.Internal.complement rB)+                                           else binAny s uA tA lB++                                    R -> if cL == x+                                           then binAny s uA tA lB+                                           else rebinL pB (binAny s uA tA lB) rB++           | otherwise      ->+               let !(# cA #) = colorR rA+                   !(# cB #) = colorL lB++               in case s of+                    L -> if cA == cB+                           then if cA == x+                                  then join pA tA+                                            pB $ Bin pB (Data.Zebra.Word.Internal.complement lB)+                                                        (Data.Zebra.Word.Internal.complement rB)+                                  else Nil Black++                           else if cA == x+                                  then Bin pB (Data.Zebra.Word.Internal.complement lB)+                                              (Data.Zebra.Word.Internal.complement rB)+                                  else tA++                    R -> if cA == cB+                           then if cA == x+                                  then Nil Black+                                  else join pB tB+                                            pA $ Bin pA (Data.Zebra.Word.Internal.complement lA)+                                                        (Data.Zebra.Word.Internal.complement rA)++                           else if cA == x+                                  then Bin pA (Data.Zebra.Word.Internal.complement lA)+                                              (Data.Zebra.Word.Internal.complement rA)+                                  else tB++        GT | pA <= upper pB -> let !(# cR #) = colorL lA+                               in case s of+                                    L -> if cR == x+                                           then binAny s uA tA rB+                                           else rebinR pB+                                                  (Data.Zebra.Word.Internal.complement lB)+                                                  (binAny s uA tA rB)++                                    R -> if cR == x+                                           then rebinR pB lB (binAny s uA tA rB)+                                           else binAny s uA tA rB++           | pB >= lower pA -> let !(# s' #) = other s++                                   !(# cL #) = colorR rB++                               in case s of+                                    L -> if cL == x+                                           then binAny s' uB tB lA+                                           else rebinL pA (binAny s' uB tB lA) rA++                                    R -> if cL == x+                                           then rebinL pA (binAny s' uB tB lA)+                                                  (Data.Zebra.Word.Internal.complement rA)++                                           else binAny s' uB tB lA++           | otherwise      ->+               let !(# cB #) = colorR rB+                   !(# cA #) = colorL lA++               in case s of+                    L -> if cA == cB+                           then if cA == x+                                  then Nil Black+                                  else join pA tA+                                            pB $ Bin pB (Data.Zebra.Word.Internal.complement lB)+                                                        (Data.Zebra.Word.Internal.complement rB)++                           else if cA == x+                                  then tA+                                  else Bin pB (Data.Zebra.Word.Internal.complement lB)+                                              (Data.Zebra.Word.Internal.complement rB)++                    R -> if cA == cB+                           then if cA == x+                                  then join pB tB+                                            pA $ Bin pA (Data.Zebra.Word.Internal.complement lA)+                                                        (Data.Zebra.Word.Internal.complement rA)+                                  else Nil Black++                           else if cA == x+                                  then tB+                                  else Bin pA (Data.Zebra.Word.Internal.complement lA)+                                              (Data.Zebra.Word.Internal.complement rA)++++-- | \(\mathcal{O}(n_A + n_B)\).+--   Symmetric difference of two trees over the given color.+symmetricDifference :: Color -> Zebra -> Zebra -> Zebra+symmetricDifference xFG l r =+  case l of+    Mono c | c == xFG  -> Data.Zebra.Word.Internal.complement r+           | otherwise -> r++    _      ->+      case r of+        Mono c | c == xFG  -> Data.Zebra.Word.Internal.complement l+               | otherwise -> l++        _      ->+          case anyAny l r of+            Nil c -> Mono c+            t     -> t+  where+    anyAny tA tB =+      case tA of+        Bin pA lA rA -> binAny (# pA, lA, rA #) tA tB++        Bla kA -> tipAny (# kA, Black #) tA tB+        Whi kA -> tipAny (# kA, White #) tA tB++        Nil _ -> tA++    tipAny uA@(# kA, cA #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin uA tA (# pB, lB, rB #) tB++        Bla kB -> goTip kB Black+        Whi kB -> goTip kB White++        Nil _ -> tB+      where+        goTip kB cB+          | kA == kB  = Nil $ if cA == cB+                                then let !(# xBG #) = invert xFG+                                     in xBG+                                else xFG++          | otherwise = let nA | (cB == xFG) == (kA < kB) = tA+                               | otherwise                = let !(# c #) = invert cA+                                                            in tip kA c++                            nB | (cA == xFG) == (kA < kB) = let !(# c #) = invert cB+                                                            in tip kB c+                               | otherwise                = tB++                        in join kA nA kB nB++    binAny uA tA tB =+      case tB of+        Bin pB lB rB -> binBin uA tA (# pB, lB, rB #) tB++        Bla kB -> tipBin (# kB, Black #) tB uA tA+        Whi kB -> tipBin (# kB, White #) tB uA tA++        Nil _ -> tB++    tipBin uA@(# kA, cA #) tA (# pB, lB, rB #) tB =+      if kA < pB+        then if kA >= lower pB+               then let r' | cA == xFG = Data.Zebra.Word.Internal.complement rB+                           | otherwise = rB++                    in rebinL pB (tipAny uA tA lB) r'++               else let !(# cL #) = colorL lB++                        nA | cL == xFG = tA+                           | otherwise = let !(# c #) = invert cA+                                         in tip kA c++                        nB | cA == xFG = Bin pB (Data.Zebra.Word.Internal.complement lB)+                                                (Data.Zebra.Word.Internal.complement rB)+                           | otherwise = tB++                    in join kA nA pB nB++        else if kA <= upper pB+               then let l' | cA == xFG = lB+                           | otherwise = Data.Zebra.Word.Internal.complement lB++                    in rebinR pB l' (tipAny uA tA rB)++               else let !(# cR #) = colorR rB++                        nA | cR == xFG = let !(# c #) = invert cA+                                         in tip kA c+                           | otherwise = tA++                        nB | cA == xFG = tB+                           | otherwise = Bin pB (Data.Zebra.Word.Internal.complement lB)+                                                (Data.Zebra.Word.Internal.complement rB)++                    in join kA nA pB nB++    binBin uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> rebin pA (anyAny lA lB) (anyAny rA rB)++        LT | pB <= upper pA -> let !(# cR #) = colorL lB++                                   l' | cR == xFG = lA+                                      | otherwise = Data.Zebra.Word.Internal.complement lA++                               in rebinR pA l' (binAny uB tB rA)++           | pA >= lower pB -> let !(# cL #) = colorR rA++                                   r' | cL == xFG = Data.Zebra.Word.Internal.complement rB+                                      | otherwise = rB++                               in rebinL pB (binAny uA tA lB) r'++           | otherwise      ->+               let !(# cA #) = colorR rA+                   !(# cB #) = colorL lB++                   nA | cB == xFG = tA+                      | otherwise = Bin pA (Data.Zebra.Word.Internal.complement lA)+                                           (Data.Zebra.Word.Internal.complement rA)++                   nB | cA == xFG = Bin pB (Data.Zebra.Word.Internal.complement lB)+                                           (Data.Zebra.Word.Internal.complement rB)+                      | otherwise = tB++               in join pA nA pB nB++        GT | pA <= upper pB -> let !(# cR #) = colorL lA++                                   l' | cR == xFG = lB+                                      | otherwise = Data.Zebra.Word.Internal.complement lB++                               in rebinR pB l' (binAny uA tA rB)++           | pB >= lower pA -> let !(# cL #) = colorR rB++                                   r' | cL == xFG = Data.Zebra.Word.Internal.complement rA+                                      | otherwise = rA++                               in rebinL pA (binAny uB tB lA) r'++           | otherwise      ->+               let !(# cB #) = colorR rB+                   !(# cA #) = colorL lA++                   nA | cB == xFG = Bin pA (Data.Zebra.Word.Internal.complement lA)+                                           (Data.Zebra.Word.Internal.complement rA)+                      | otherwise = tA++                   nB | cA == xFG = tB+                      | otherwise = Bin pB (Data.Zebra.Word.Internal.complement lB)+                                           (Data.Zebra.Word.Internal.complement rB)+               in join pA nA pB nB++++data S = L | R+         deriving Show++other :: S -> (# S #)+other L = (# R #)+other R = (# L #)++-- | \(\mathcal{O}(n_A + n_B)\).+--    Compare two trees with respect to set inclusion over the given color.+compare :: Color -> Zebra -> Zebra -> PartialOrdering+compare x l r =+  case l of+    Mono cA ->+      case r of+        Mono cB | cA == cB  -> Equal+                | cA == x   -> Superset+                | otherwise -> Subset++        _       | cA == x   -> Superset+                | otherwise -> Subset+    _      ->+      case r of+        Mono cB | cB == x   -> Subset+                | otherwise -> Superset++        _      -> anyAny L l r+  where+    anyAny s tA tB =+      case tA of+        Bin pA lA rA -> binAny s (# pA, lA, rA #) tA tB++        Bla kA -> tipAny s (# kA, Black #) tA tB+        Whi kA -> tipAny s (# kA, White #) tA tB++        Nil _ -> Incomparable++    tipAny s uA@(# kA, cA #) tA tB =+      case tB of+        Bin pB lB rB -> tipBin s uA tA (# pB, lB, rB #)++        Bla kB -> goTip kB Black+        Whi kB -> goTip kB White++        Nil _ -> Incomparable+      where+        goTip kB cB+          | cA == cB  = if kA == kB+                          then Equal+                          else if (cA == x) == (kA < kB)+                                 then case s of+                                        L -> Superset+                                        R -> Subset++                                 else case s of+                                        L -> Subset+                                        R -> Superset++          | otherwise = Incomparable++    binAny s uA tA tB =+      case tB of+        Bin pB lB rB -> binBin s uA tA (# pB, lB, rB #) tB++        Bla kB -> goTip kB Black+        Whi kB -> goTip kB White++        Nil _ -> Incomparable+      where+        goTip kB cB = let !(# s' #) = other s+                      in tipBin s' (# kB, cB #) tB uA++    tipBin s uA@(# kA, cA #) tA (# pB, lB, rB #) =+      if kA < pB+        then if kA >= lower pB+               then let !(# o #) = if cA == x+                                     then case s of+                                            L -> (# Superset #)+                                            R -> (# Subset #)++                                     else case s of+                                            L -> (# Subset #)+                                            R -> (# Superset #)++                    in order o (tipAny s uA tA lB)++               else let !(# cR #) = colorL lB+                    in if cA == cR+                         then if cA == x+                                then case s of+                                       L -> Superset+                                       R -> Subset++                                else case s of+                                       L -> Subset+                                       R -> Superset++                         else Incomparable++        else if kA <= upper pB+               then let !(# o #) = if cA == x+                                     then case s of+                                            L -> (# Subset #)+                                            R -> (# Superset #)++                                     else case s of+                                            L -> (# Superset #)+                                            R -> (# Subset #)++                    in order o (tipAny s uA tA rB)++               else let !(# cL #) = colorR rB+                    in if cA == cL+                         then if cA == x+                                then case s of+                                       L -> Subset+                                       R -> Superset++                                else case s of+                                       L -> Superset+                                       R -> Subset++                         else Incomparable++    binBin s uA@(# pA, lA, rA #) tA uB@(# pB, lB, rB #) tB =+      case Prelude.compare pA pB of+        EQ                  -> order (anyAny s lA lB) (anyAny s rA rB)++        LT | pB <= upper pA -> let !(# s' #) = other s++                                   !(# cR #) = colorL lB++                                   !(# o #) = if cR == x+                                                then case s of+                                                       L -> (# Superset #)+                                                       R -> (# Subset #)++                                                else case s of+                                                       L -> (# Subset #)+                                                       R -> (# Superset #)++                               in order o (binAny s' uB tB rA)++           | pA >= lower pB -> let !(# cL #) = colorR rA++                                   !(# o #) = if cL == x+                                                then case s of+                                                       L -> (# Superset #)+                                                       R -> (# Subset #)++                                                else case s of+                                                       L -> (# Subset #)+                                                       R -> (# Superset #)++                               in order o (binAny s uA tA lB)++           | otherwise      -> let !(# cL #) = colorR rA+                                   !(# cR #) = colorL lB++                               in if cL == cR+                                    then if cL == x+                                           then case s of+                                                  L -> Superset+                                                  R -> Subset++                                           else case s of+                                                  L -> Subset+                                                  R -> Superset++                                    else Incomparable++        GT | pA <= upper pB -> let !(# cR #) = colorL lA++                                   !(# o #) = if cR == x+                                                then case s of+                                                       L -> (# Subset #)+                                                       R -> (# Superset #)++                                                else case s of+                                                       L -> (# Superset #)+                                                       R -> (# Subset #)++                               in order o (binAny s uA tA rB)++           | pB >= lower pA -> let !(# s' #) = other s++                                   !(# cL #) = colorR rB++                                   !(# o #) = if cL == x+                                                then case s of+                                                       L -> (# Subset #)+                                                       R -> (# Superset #)++                                                else case s of+                                                       L -> (# Superset #)+                                                       R -> (# Subset #)++                               in order o (binAny s' uB tB lA)++           | otherwise      -> let !(# cL #) = colorR rB+                                   !(# cR #) = colorL lA++                               in if cL == cR+                                    then if cL == x+                                           then case s of+                                                  L -> Subset+                                                  R -> Superset++                                           else case s of+                                                  L -> Superset+                                                  R -> Subset++                                    else Incomparable
+ src/Data/Zebra/Word/Unsafe.hs view
@@ -0,0 +1,76 @@+{-# OPTIONS_HADDOCK not-home #-}++{-|+    Data structure internals, helper operations and unsafe functions.++    == Implementation++    The tree is structurally identical to the+    'Data.Patricia.Word.Strict.Unsafe.Patricia' tree, holding 'Color's as values.++    A key \(k\) in the tree denotes a right-open interval+    \([k, k_R)\) within which every key has the same color as \(k\). \(k_R\) is the key+    immediately to the right of \(k\), or, if \(k\) is the rightmost key, \(+\infty\).++    Two adjacent intervals __must not__ have the same color. This both removes+    redundancies and allows to make assumptions about the color of the key+    immediately to the left.++    The following is a visual example of a possible 4-bit tree under these rules:++    ![4-bit tree](https://raw.githubusercontent.com/sergv/radix-tree/master/images/4bit.svg)+ -}++module Data.Zebra.Word.Unsafe+  ( Zebra (..)+  , Color (..)++    -- * Bit operations+  , Prefix+  , Key++    -- | === Compare+  , beyond+  , upper+  , lower++    -- | === Create+  , Mask+  , zeroBit+  , mask+  , branchingBit++    -- * Directional+    -- ** Size+  , unsafeSizeL+  , unsafeSizeR++    -- ** Insert+  , unsafeFillL++    -- * Range+  , Range (..)++    -- ** Size+  , unsafeMonoRange+  , unsafeSizeRange++    -- ** Insert+  , unsafeFillRange++    -- ** Fold+    -- | === Left-to-right+  , unsafeFoldlRange+  , unsafeFoldlRange'++    -- | === Right-to-left+  , unsafeFoldrRange+  , unsafeFoldrRange'++    -- * Full tree+    -- ** Size+  , unsafeSize+  ) where++import           Data.Zebra.Word.Internal+import           Radix.Word.Foundation
+ src/Numeric/Long.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Numeric.Long+  ( showLongHex+  , showLongBin+  , showPrefix+  ) where++import           Data.Bits+import           Data.Char++++showLongHex :: (FiniteBits a, Integral a, Num a) => a -> ShowS+showLongHex (w0 :: a) = go w0 0+  where+    go w n+      | n >= finiteBitSize (0 :: a) = id+      | otherwise                   =+          let (q, r) = quotRem w 16+          in go q (n + 4 :: Int) . showChar (intToDigit (fromIntegral r))++++showLongBin :: (FiniteBits a, Integral a, Num a) => a -> ShowS+showLongBin (w :: a) = go 0+  where+    go n+      | n >= finiteBitSize (0 :: a) = id+      | otherwise                   =+          go (n + 1) . showChar (chr . fromIntegral $ 48 + (unsafeShiftR w n .&. 1))++++showPrefix :: (FiniteBits a, Integral a, Num a) => a -> ShowS+showPrefix (w :: a) = go 0+  where+    m = w .&. negate w++    go n+      | n >= finiteBitSize (0 :: a) = id+      | otherwise                   =+          go (n + 1) . showChar+                         ( if unsafeShiftL 1 n >= m+                             then chr . fromIntegral $ 48 + (unsafeShiftR w n .&. 1)+                             else 'X'+                         )
+ src/Radix/Common.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE GADTs+           , UnboxedTuples #-}++module Radix.Common+  ( PartialOrdering (..)+  , order++  , S (..)+  , other+  , limit+  ) where++++-- | Comparison of two sets, \(A\) and \(B\) respectively.+data PartialOrdering = Subset       -- ^ \(A \subset B\).+                     | Superset     -- ^ \(A \supset B\).+                     | Equal        -- ^ \(A = B\).+                     | Incomparable -- ^ \(A \parallel B\).+                       deriving (Show, Eq)++-- | Comparison of two partial orderings.+order :: PartialOrdering -> PartialOrdering -> PartialOrdering+order Subset   Subset   = Subset+order Subset   Equal    = Subset++order Superset Superset = Superset+order Superset Equal    = Superset++order Equal    o        = o++order _        _        = Incomparable++++-- | Merge side.+data S a b x y where+  L :: S x y x y+  R :: S y x x y++-- | The other merge side.+other :: S a b x y -> (# S b a x y #)+other L = (# R #)+other R = (# L #)++-- | Limits the left side to a 'Subset'.+limit :: S x y a b -> PartialOrdering -> PartialOrdering+limit L Superset = Incomparable+limit R Subset   = Incomparable+limit s Equal    = case s of+                     L -> Subset+                     R -> Superset+limit _ o        = o
+ src/Radix/Exception.hs view
@@ -0,0 +1,21 @@+module Radix.Exception+  ( MalformedTree (..)+  ) where++import           Control.Exception++++-- | Exception thrown by functions that need to return a value,+--   but instead find an invariant-breaking empty node.+data MalformedTree = MalformedTree+                       String -- ^ Module name+                       String -- ^ Function name++instance Show MalformedTree where+  showsPrec _ (MalformedTree loc fun) =+    showString "radix-tree#"+      . showString loc . showChar '.'+      . showString fun . showString ": Encountered Nil, tree is malformed"++instance Exception MalformedTree
+ src/Radix/Word/Common.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE PatternSynonyms #-}++module Radix.Word.Common+  ( Range (Range, ..)+  ) where++import           Radix.Word.Foundation++++-- | A closed interval between two keys.+data Range = -- | Invariant: \(k_L \le k_R\).+             UnsafeRange+               {-# UNPACK #-} !Key -- ^ \(k_L\)+               {-# UNPACK #-} !Key -- ^ \(k_R\)++instance Show Range where+  showsPrec d (UnsafeRange kL kR) =+    showParen (d > 10) $+      showString "Range " . shows kL+           . showChar ' ' . shows kR++{-# COMPLETE Range #-}+-- | Reorders endpoints to fit mathematical notation:+--   \([12, 3]\) will be converted to \([3, 12]\).+--+--   Pattern matching guarantees \(k_1 \le k_2\).+pattern Range+  :: Word  -- ^ \(k_1\)+  -> Word  -- ^ \(k_2\)+  -> Range+pattern Range kL kR <- UnsafeRange kL kR+  where+    Range k1 k2+      | k1 <= k2  = UnsafeRange k1 k2+      | otherwise = UnsafeRange k2 k1
+ src/Radix/Word/Debug.hs view
@@ -0,0 +1,23 @@+module Radix.Word.Debug+  ( S (..)+  , validBelow+  ) where++import           Radix.Word.Foundation++import           Data.Bits++++-- | Branch side.+data S = L -- ^ Left. Masked bit of the prefix above this node must be @0@.+       | R -- ^ Right. Masked bit of the prefix above this node must be @1@.+         deriving Show++-- | Check whether the key below aligns with the side the branch is on.+validBelow :: Prefix -> S -> Key -> Bool+validBelow p1 s p2 =+  let q = p2 .&. (p1 .&. negate p1)+  in not (beyond p1 p2) && case s of+                             L -> q == 0+                             R -> q /= 0
+ src/Radix/Word/Foundation.hs view
@@ -0,0 +1,68 @@+module Radix.Word.Foundation+  ( Key+  , Prefix+  , Mask++  , beyond+  , upper+  , lower++  , zeroBit+  , mask+  , branchingBit+  ) where++import           Data.Bits++++-- | Key as stored in the data structure.+type Key = Word++-- | Part of the 'Key' from the largest bit to the 'Mask' bit, plus the 'Mask' bit.+type Prefix = Word++{-# INLINE beyond #-}+-- | \(\mathcal{O}(1)\).+--   Whether the key does not match the prefix.+beyond :: Prefix -> Key -> Bool+beyond p k = (k `xor` p) .&. (p `xor` negate p) /= 0++{-# INLINE upper #-}+-- | \(\mathcal{O}(1)\).+--   Largest key that can reside under this prefix.+upper :: Prefix -> Key+upper p = p .|. (p - 1)++{-# INLINE lower #-}+-- | \(\mathcal{O}(1)\).+--   Smallest key that can reside under this prefix.+lower :: Prefix -> Key+lower p = p .&. (p - 1)++++-- | Masking bit.+type Mask = Word++{-# INLINE zeroBit #-}+-- | \(\mathcal{O}(1)\).+--   Get the state of the masked bit from the 'Key'.+zeroBit :: Key -> Mask -> Bool+zeroBit k m = (k .&. m) == 0++{-# INLINE mask #-}+-- | \(\mathcal{O}(1)\).+--   Trim the 'Key' down to the masking bit.+mask :: Key -> Mask -> Word+mask k m = k .&. (negate m `xor` m)++{-# INLINE branchingBit #-}+-- | \(\mathcal{O}(1)\).+--   Find the bit two 'Prefix'es disagree on.+--+--   Note that using this function on two equal integers yields @1 << (-1)@,+--   which results in undefined behavior.+branchingBit :: Prefix -> Prefix -> Mask+branchingBit p o =+  1 `unsafeShiftL` (finiteBitSize (0 :: Word) - 1 - countLeadingZeros (p `xor` o))
+ src/Radix/Word8/Common.hs view
@@ -0,0 +1,10 @@+module Radix.Word8.Common+  ( Location (..)+  ) where++++-- | Whether the cursor point to a point within the tree.+data Location = Inside+              | Outside+                deriving Show
+ src/Radix/Word8/Debug.hs view
@@ -0,0 +1,23 @@+module Radix.Word8.Debug+  ( S (..)+  , validBelow+  ) where++import           Radix.Word8.Foundation++import           Data.Bits++++-- | Branch side.+data S = L -- ^ Left. Masked bit of the prefix above this node must be @0@.+       | R -- ^ Right. Masked bit of the prefix above this node must be @1@.+         deriving Show++-- | Check whether the key below aligns with the side the branch is on.+validBelow :: Prefix -> S -> Key -> Bool+validBelow p1 s p2 =+  let q = p2 .&. (p1 .&. negate p1)+  in not (beyond p1 p2) && case s of+                             L -> q == 0+                             R -> q /= 0
+ src/Radix/Word8/Foundation.hs view
@@ -0,0 +1,62 @@+module Radix.Word8.Foundation+  ( Key+  , Prefix+  , Mask++  , beyond+  , upper+  , lower++  , zeroBit+  , mask+  , branchingBit+  ) where++import           Data.Bits+import           Data.Word++++-- | Key as stored in the data structure.+type Key = Word8++-- | Part of the 'Key' from the largest bit to the 'Mask' bit, plus the 'Mask' bit.+type Prefix = Word8++{-# INLINE beyond #-}+-- | \(\mathcal{O}(1)\).+--   Whether the key does not match the prefix.+beyond :: Prefix -> Key -> Bool+beyond p k = (k `xor` p) .&. (p `xor` negate p) /= 0++{-# INLINE upper #-}+-- | \(\mathcal{O}(1)\).+--   Largest key that can reside under this prefix.+upper :: Prefix -> Key+upper p = p .|. (p - 1)++{-# INLINE lower #-}+-- | \(\mathcal{O}(1)\).+--   Smallest key that can reside under this prefix.+lower :: Prefix -> Key+lower p = p .&. (p - 1)++++-- | Masking bit.+type Mask = Word8++{-# INLINE zeroBit #-}+-- | Get the state of the masked bit from the 'Key'.+zeroBit :: Key -> Mask -> Bool+zeroBit k m = (k .&. m) == 0++{-# INLINE mask #-}+-- | Trim the 'Key' down to a 'Prefix'.+mask :: Key -> Mask -> Prefix+mask k m = k .&. (negate m `xor` m)++{-# INLINE branchingBit #-}+-- | Finds the bit the two 'Prefix'es disagree on.+branchingBit :: Prefix -> Prefix -> Mask+branchingBit p o = 1 `unsafeShiftL` (7 - countLeadingZeros (p `xor` o))
− test/TestMain.hs
@@ -1,119 +0,0 @@-------------------------------------------------------------------------------- |--- Module      :  TestMain--- Copyright   :  (c) Sergey Vinokurov 2018--- License     :  BSD3-style (see LICENSE)--- Maintainer  :  serg.foo@gmail.com-------------------------------------------------------------------------------{-# LANGUAGE ScopedTypeVariables #-}--{-# OPTIONS_GHC -Wno-orphans #-}--module Main (main) where--import Data.ByteString.Short (ShortByteString)-import qualified Data.ByteString.Short as BSS--import Data.Char-import Data.Map.Strict (Map)-import qualified Data.Map.Strict as M-import Data.RadixTree (RadixTree)-import qualified Data.RadixTree as RT-import Data.Word--import Test.QuickCheck-import Test.QuickCheck.Poly-import Test.Tasty-import Test.Tasty.QuickCheck as QC--newtype AsciiChar = AsciiChar { unAsciiChar :: Char }--instance Arbitrary AsciiChar where-  arbitrary = AsciiChar <$> choose ('a', 'z')-  shrink (AsciiChar 'a') = []-  shrink (AsciiChar c)   = [AsciiChar c' | c' <- ['a'..pred c]]--mkAsciiChar :: Word8 -> AsciiChar-mkAsciiChar = AsciiChar . chr. fromIntegral--asciiByte :: AsciiChar -> Word8-asciiByte = fromIntegral . ord . unAsciiChar--instance Arbitrary ShortByteString where-  arbitrary =-    BSS.pack . map asciiByte <$> listOf arbitrary-  shrink =-    map (BSS.pack . map asciiByte) . shrink . map mkAsciiChar . BSS.unpack--instance Arbitrary a => Arbitrary (RadixTree a) where-  arbitrary = RT.fromList <$> arbitrary-  shrink = map RT.fromList . shrink . RT.toAscList--main :: IO ()-main = defaultMain tests--tests :: TestTree-tests = testGroup "Tests" [properties]--properties :: TestTree-properties = testGroup "Properties" [qcProps]--qcProps :: TestTree-qcProps = adjustOption (\(QuickCheckTests n) -> QuickCheckTests (max 10000 n)) $ testGroup "radix tree"-  [ QC.testProperty "∀ t: RT.lookup k (RT.insert k v t) == v" $-    \(t :: RadixTree A) (k :: ShortByteString) (v :: A) ->-      RT.lookup k (RT.insert k v t) == Just v-  , QC.testProperty "∀ t: RT.lookup k (RT.insert k v2 (RT.insert k v1 t)) == v2" $-    \(t :: RadixTree A) (k :: ShortByteString) (v1 :: A) (v2 :: A) ->-      RT.lookup k (RT.insert k v2 (RT.insert k v1 t)) == Just v2--  , QC.testProperty "∀ xs: RT.fromList xs == M.fromList xs" $-    \(xs :: [(ShortByteString, A)]) ->-      RT.toAscList (RT.fromList xs) == M.toAscList (M.fromList xs)--  , QC.testProperty "∀ xs: RT.size (RT.fromList xs) == M.size (M.fromList xs)" $-    \(xs :: [(ShortByteString, A)]) ->-      RT.size (RT.fromList xs) == M.size (M.fromList xs)--  , QC.testProperty "∀ f: RT.mapMaybe f == M.mapMaybe f" $-    \(f :: Fun A (Maybe B)) ->-      RT.mapMaybe (applyFun f) ==== M.mapMaybe (applyFun f)--  , QC.testProperty "∀ k v t: RT.insert k v t == M.insert k v t" $-    \(k :: ShortByteString) (v :: A) ->-      RT.insert k v ==== M.insert k v--  , QC.testProperty "∀ f xs ys: RT.mergeWith f xs ys == M.mergeWith f xs ys" $-    \(f :: Fun (A, A) A) ->-      RT.unionWith (curry (applyFun f)) ===== M.unionWith (curry (applyFun f))-  ]--(====)-  :: Eq b-  => (RadixTree a -> RadixTree b)-  -> (Map ShortByteString a -> Map ShortByteString b)-  -> [(ShortByteString, a)]-  -> Bool-(====) f g xs =-  RT.toAscList (f (RT.fromList xs)) == M.toAscList (g (M.fromList xs))--(=====)-  :: Eq a-  => (RadixTree a -> RadixTree a -> RadixTree a)-  -> (Map ShortByteString a -> Map ShortByteString a -> Map ShortByteString a)-  -> [(ShortByteString, a)]-  -> [(ShortByteString, a)]-  -> Bool-(=====) f g xs ys =-  RT.toAscList (f (RT.fromList xs) (RT.fromList ys)) == M.toAscList (g (M.fromList xs) (M.fromList ys))---- unitTests :: TestTree--- unitTests = testGroup "Unit tests"---   [ testCase "List comparison (different length)" $---       [1, 2, 3] `compare` [1,2] @?= GT------   -- the following test does not hold---   , testCase "List comparison (same length)" $---       [1, 2, 3] `compare` [1,2,2] @?= LT---   ]
+ test/properties/Main.hs view
@@ -0,0 +1,33 @@+module Main where++import qualified Test.Patricia.Word.Lazy as Pat.Lazy+import qualified Test.Patricia.Word.Strict as Pat.Strict+import qualified Test.RadixTree.Word8.Lazy as Radix.Lazy+import qualified Test.RadixTree.Word8.Strict as Radix.Strict+import qualified Test.RadixNTree.Word8.Key as Radix.Key+import qualified Test.Zebra.Word as Zebra++import           Test.Hspec++++main :: IO ()+main =+  hspec $ do+    describe "Patricia/Lazy" $+      Pat.Lazy.test++    describe "Patricia/Strict" $+      Pat.Strict.test++    describe "RadixNTree/Key" $+      Radix.Key.test++    describe "RadixTree/Lazy" $+      Radix.Lazy.test++    describe "RadixTree/Strict" $+      Radix.Strict.test++    describe "Zebra" $+      Zebra.test
+ test/properties/Test/Kit.hs view
@@ -0,0 +1,60 @@+module Test.Kit+  ( Case (..)+  , augment++  , Test (..)++  , run+  , dump+  ) where++import           Control.Exception+import           Data.Foldable++++data Case s a b = Case s a b++augment :: (s -> t) -> [Case s a b] -> [Case t a b]+augment f xs = fmap (\(Case s a b) -> Case (f s) a b) xs++++data Test s a b x y = Test (x -> y -> Bool) (s -> a -> x) (s -> b -> y)++++newtype Failure = Failure Int++instance Show Failure where+  showsPrec _ (Failure n) = showString "Test failed on case " . shows n++instance Exception Failure++++newtype UnknownIndex = UnknownIndex Int++instance Show UnknownIndex where+  showsPrec _ (UnknownIndex n) = showString "No case under index " . shows n++instance Exception UnknownIndex++++enumerate :: [Case s a b] -> [(Int, Case s a b)]+enumerate = zip [0..]++run :: [Case s a b] -> Test s a b x y -> IO ()+run cs (Test cmp f g) = traverse_ go $ enumerate cs+  where+    go (n, Case s a b) = +      if cmp (f s a) (g s b)+        then pure ()+        else throwIO (Failure n)++dump :: [Case s a b] -> Test s a b x y -> Int -> IO (s, a, b, x, y)+dump xs (Test _ f g) n =+  case lookup n (enumerate xs) of+    Just (Case s a b) -> pure (s, a, b, f s a, g s b)+    Nothing           -> throwIO (UnknownIndex n)
+ test/properties/Test/Patricia/Word/Lazy.hs view
@@ -0,0 +1,795 @@+{-# LANGUAGE RankNTypes #-}++module Test.Patricia.Word.Lazy+  ( test+  ) where++import           Data.Patricia.Word.Lazy (Patricia)+import qualified Data.Patricia.Word.Lazy as Pat+import           Data.Patricia.Word.Lazy.Debug (validate, Validity (..))+import qualified Data.Patricia.Word.Lazy.Unsafe as Pat+import           No.Tree (NoTree)+import qualified No.Tree as No+import           Test.Patricia.Word.Sample+import           Test.Kit++import           Data.Functor.Identity+import           Test.Hspec++++patFromList :: [(Word, a)] -> Patricia a+patFromList = foldr (\(k, a) p -> Pat.insert k a p) Pat.empty++patToList :: Patricia a -> [(Word, a)]+patToList = Pat.foldrWithKey (\k a -> (:) (k, a)) []++++patRange :: (Pat.Range -> a -> b) -> (Word, Word, a) -> b+patRange f (k1, k2, a) = f (Pat.Range k1 k2) a++patRange_ :: (Pat.Range -> b) -> (Word, Word) -> b+patRange_ f (k1, k2) = f (Pat.Range k1 k2)++noRange :: (No.Range Word -> a -> b) -> (Word, Word, a) -> b+noRange f (k1, k2, a) = f (No.WordRange No.Closed k1 No.Closed k2) a++noRange_ :: (No.Range Word -> b) -> (Word, Word) -> b+noRange_ f (k1, k2) = f (No.WordRange No.Closed k1 No.Closed k2)++++unary0 :: [Case () (Patricia Int) (NoTree Word Int)]+unary0 = foldMap (mkUnary0 patFromList) [zero, one, tiny, small, medium] -- , large]++unary1 :: [Case (Word, Int) (Patricia Int) (NoTree Word Int)]+unary1 = foldMap (mkUnary1 patFromList) [zero, one, tiny, small, medium] -- , large]++unary1_ :: [Case Word (Patricia Int) (NoTree Word Int)]+unary1_ = augment fst unary1++unary2 :: [Case (Word, Word, Int) (Patricia Int) (NoTree Word Int)]+unary2 = foldMap (mkUnary2 patFromList) [zero, one, tiny, small, medium] -- , large]++unary2_ :: [Case (Word, Word) (Patricia Int) (NoTree Word Int)]+unary2_ = augment (\(k1, k2, _) -> (k1, k2)) unary2++binary+  , binaryL+  , subset+  , superset+  , equal+ :: [Case (Patricia Int, NoTree Word Int) (Patricia Int) (NoTree Word Int)]+binary   = foldMap (mkBinary   patFromList) [zero, one, tiny, small, medium] -- , large]+binaryL  = foldMap (mkBinaryL  patFromList) [zero, one, tiny, small, medium] -- , large]+subset   = foldMap (mkSubset   patFromList) [zero, one, tiny, small, medium] -- , large]+superset = foldMap (mkSuperset patFromList) [zero, one, tiny, small, medium] -- , large]+equal    = foldMap (mkEqual    patFromList) [zero, one, tiny, small, medium] -- , large]++++type IdT s a b = Test s (Patricia a) (NoTree Word a) b b++type TreeT s a = Test s (Patricia a) (NoTree Word a) (Patricia a) (NoTree Word a)++treeEq :: Eq a => Patricia a -> NoTree Word a -> Bool+treeEq pat no =+  case validate pat of+    Valid -> patToList pat == No.toList no+    _     -> False++type SplitT s a =+       Test s (Patricia a) (NoTree Word a)+         (Patricia a, Patricia a) (NoTree Word a, NoTree Word a)++splitEq+  :: Eq a => (Patricia a, Patricia a) -> (NoTree Word a, NoTree Word a) -> Bool+splitEq (a, b) (x, y) = treeEq a x && treeEq b y++type SplitLookupT s a =+       Test s (Patricia a) (NoTree Word a)+         (Patricia a, Maybe a, Patricia a) (NoTree Word a, Maybe a, NoTree Word a)++splitLookupEq+  :: Eq a+  => (Patricia a, Maybe a, Patricia a) -> (NoTree Word a, Maybe a, NoTree Word a) -> Bool+splitLookupEq (a, b, c) (x, y, z) = treeEq a x && b == y && treeEq c z++type LookupT s a =+       Test s (Patricia a) (NoTree Word a) (Maybe (Pat.Lookup a)) (Maybe (Word, a))++lookupEq :: Eq a => Maybe (Pat.Lookup a) -> Maybe (Word, a) -> Bool+lookupEq (Just (Pat.Lookup k a)) (Just (l, b)) = k == l && a == b+lookupEq Nothing                 Nothing       = True+lookupEq _                       _             = False++type MinViewT s a =+       Test s (Patricia a) (NoTree Word a)+         (Maybe (Pat.ViewL a)) (Maybe (Word, a, NoTree Word a))++minViewEq :: Eq a => Maybe (Pat.ViewL a) -> Maybe (Word, a, NoTree Word a) -> Bool+minViewEq (Just (Pat.ViewL (Pat.Lookup k a) pat)) (Just (l, b, no)) =+  k == l && a == b && treeEq pat no++minViewEq Nothing Nothing = True+minViewEq _       _       = False++type MaxViewT s a =+       Test s (Patricia a) (NoTree Word a)+         (Maybe (Pat.ViewR a)) (Maybe (NoTree Word a, Word, a))++maxViewEq :: Eq a => Maybe (Pat.ViewR a) -> Maybe (NoTree Word a, Word, a) -> Bool+maxViewEq (Just (Pat.ViewR pat (Pat.Lookup k a))) (Just (no, l, b)) =+  k == l && a == b && treeEq pat no++maxViewEq Nothing Nothing = True+maxViewEq _       _       = False++++lookupT :: Eq a => IdT Word a (Maybe a)+lookupT = Test (==) Pat.lookup No.lookup++findT :: Eq a => IdT (Word, a) a a+findT = Test (==) (\(k, a) -> Pat.find a k) (\(k, a) -> No.find a k)++memberT :: IdT Word a Bool+memberT = Test (==) Pat.member No.member++++insertT :: Eq a => TreeT (Word, a) a+insertT = Test treeEq (uncurry Pat.insert) (uncurry No.insert)++insertWithT :: (Eq a, Integral a) => TreeT (Word, a) a+insertWithT =+  let f x = (+ fromIntegral x)+  in Test treeEq+       (\(k, a) -> Pat.insertWith (f a) k a)+       (\(k, a) -> No.insertWith (f a) k a)++adjustT :: (Eq a, Integral a) => TreeT (Word, a) a+adjustT =+  let f a = (+ fromIntegral a)+  in Test treeEq (\(k, a) -> Pat.adjust (f a) k) (\(k, a) -> No.adjust (f a) k)++deleteT :: Eq a => TreeT Word a+deleteT = Test treeEq Pat.delete No.delete++updateAdjustT, updateDeleteT :: (Eq a, Integral a) => TreeT (Word, a) a+updateAdjustT = updateT_ (\a -> Just . (+ a))+updateDeleteT = updateT_ (\_ _ -> Nothing)++updateT_ :: Eq a => (a -> a -> Maybe a) -> TreeT (Word, a) a+updateT_ f = Test treeEq (\(k, a) -> Pat.update (f a) k) (\(k, a) -> No.update (f a) k)++alterInsertT+  , alterInsertWithT+  , alterAdjustT+  , alterDeleteT+ :: (Eq a, Integral a) => TreeT (Word, a) a+alterInsertT     = alterT_ (\a _ -> Just a)+alterInsertWithT = alterT_ (\a -> Just . maybe a (+ a))+alterAdjustT     = alterT_ (\a -> fmap (+ a))+alterDeleteT     = alterT_ (\_ _ -> Nothing)++alterT_ :: Eq a => (a -> Maybe a -> Maybe a) -> TreeT (Word, a) a+alterT_ f = Test treeEq (\(k, a) -> Pat.alter (f a) k) (\(k, a) -> No.alter (f a) k)++++splitLT :: Eq a => SplitT Word a+splitLT = Test splitEq Pat.splitL (No.splitL No.Closed)++splitRT :: Eq a => SplitT Word a+splitRT = Test splitEq Pat.splitR No.splitR++splitLookupT :: Eq a => SplitLookupT Word a+splitLookupT = Test splitLookupEq Pat.splitLookup No.splitLookup++++lookupLT :: Eq a => LookupT Word a+lookupLT = Test lookupEq Pat.lookupL (No.lookupL No.Closed)++adjustLT :: (Eq a, Integral a) => TreeT (Word, a) a+adjustLT =+  let f a = (+ a)+  in Test treeEq+       (\(k, a) -> Pat.adjustL (f a) k)+       (\(k, a) -> No.adjustL (f a) No.Closed k)++adjustLWithKeyT :: (Eq a, Integral a) => TreeT (Word, a) a+adjustLWithKeyT =+  let f a k = (+ fromIntegral k) . (+ a)+  in Test treeEq+       (\(k, a) -> Pat.adjustLWithKey (f a) k)+       (\(k, a) -> No.adjustLWithKey (f a) No.Closed k)++deleteLT :: Eq a => TreeT (Word) a+deleteLT = Test treeEq Pat.deleteL (No.deleteL No.Closed)++updateLAdjustT+  , updateLDeleteT+ :: (Eq a, Integral a) => TreeT (Word, a) a+updateLAdjustT = updateLT_ (\a -> Just . (+ a))+updateLDeleteT = updateLT_ (\_ _ -> Nothing)++updateLT_+  :: (Eq a, Integral a)+  => (a -> a -> Maybe a) -> TreeT (Word, a) a+updateLT_ f =+  Test treeEq (\(k, a) -> Pat.updateL (f a) k) (\(k, a) -> No.updateL (f a) No.Closed k)++updateLWithKeyAdjustT+  , updateLWithKeyDeleteT+ :: (Eq a, Integral a) => TreeT (Word, a) a+updateLWithKeyAdjustT = updateLWithKeyT_ (\a k -> Just . (+ fromIntegral k) . (+ a))+updateLWithKeyDeleteT = updateLWithKeyT_ (\_ _ _ -> Nothing)++updateLWithKeyT_+  :: (Eq a, Integral a)+  => (a -> Word -> a -> Maybe a) -> TreeT (Word, a) a+updateLWithKeyT_ f =+  Test treeEq (\(k, a) -> Pat.updateLWithKey (f a) k)+              (\(k, a) -> No.updateLWithKey (f a) No.Closed k)++takeLT :: Eq a => TreeT (Word) a+takeLT = Test treeEq Pat.takeL (No.takeL No.Closed)++++lookupRT :: Eq a => LookupT (Word) a+lookupRT = Test lookupEq Pat.lookupR (No.lookupR No.Closed)++adjustRT :: (Eq a, Integral a) => TreeT (Word, a) a+adjustRT =+  let f a = (+ a)+  in Test treeEq+       (\(k, a) -> Pat.adjustR (f a) k)+       (\(k, a) -> No.adjustR (f a) No.Closed k)++adjustRWithKeyT :: (Eq a, Integral a) => TreeT (Word, a) a+adjustRWithKeyT =+  let f a k = (+ fromIntegral k) . (+ a)+  in Test treeEq+       (\(k, a) -> Pat.adjustRWithKey (f a) k)+       (\(k, a) -> No.adjustRWithKey (f a) No.Closed k)++deleteRT :: Eq a => TreeT (Word) a+deleteRT = Test treeEq Pat.deleteR (No.deleteR No.Closed)++updateRAdjustT+  , updateRDeleteT+ :: (Eq a, Integral a) => TreeT (Word, a) a+updateRAdjustT = updateRT_ (\a -> Just . (+ a))+updateRDeleteT = updateRT_ (\_ _ -> Nothing)++updateRT_+  :: (Eq a, Integral a)+  => (a -> a -> Maybe a) -> TreeT (Word, a) a+updateRT_ f =+  Test treeEq (\(k, a) -> Pat.updateR (f a) k) (\(k, a) -> No.updateR (f a) No.Closed k)++updateRWithKeyAdjustT+  , updateRWithKeyDeleteT+ :: (Eq a, Integral a) => TreeT (Word, a) a+updateRWithKeyAdjustT = updateRWithKeyT_ (\a k -> Just . (+ fromIntegral k) . (+ a))+updateRWithKeyDeleteT = updateRWithKeyT_ (\_ _ _ -> Nothing)++updateRWithKeyT_+  :: (Eq a, Integral a)+  => (a -> Word -> a -> Maybe a) -> TreeT (Word, a) a+updateRWithKeyT_ f =+  Test treeEq (\(k, a) -> Pat.updateRWithKey (f a) k)+              (\(k, a) -> No.updateRWithKey (f a) No.Closed k)++takeRT :: Eq a => TreeT (Word) a+takeRT = Test treeEq Pat.takeR (No.takeR No.Closed)++++adjustRangeT :: (Eq a, Integral a) => TreeT (Word, Word, a) a+adjustRangeT =+  let f a = (+ a)+  in Test treeEq+       (patRange $ \r a -> Pat.adjustRange (f a) r)+       (noRange $ \r a -> No.adjustRange (f a) r)++adjustRangeWithKeyT :: (Eq a, Integral a) => TreeT (Word, Word, a) a+adjustRangeWithKeyT =+  let f a k = (+ fromIntegral k) . (+ a)+  in Test treeEq+       (patRange $ \r a -> Pat.adjustRangeWithKey (f a) r)+       (noRange $ \r a -> No.adjustRangeWithKey (f a) r)++deleteRangeT :: Eq a => TreeT (Word, Word) a+deleteRangeT = Test treeEq (patRange_ Pat.deleteRange) (noRange_ No.deleteRange)++updateRangeAdjustT+  , updateRangeDeleteT+ :: (Eq a, Integral a) => TreeT (Word, Word, a) a+updateRangeAdjustT = updateRangeT_ (\a -> Just . (+ a))+updateRangeDeleteT = updateRangeT_ (\_ _ -> Nothing)++updateRangeT_+  :: (Eq a, Integral a)+  => (a -> a -> Maybe a) -> TreeT (Word, Word, a) a+updateRangeT_ f =+  Test treeEq+    (patRange $ \r a -> Pat.updateRange (f a) r) (noRange $ \r a -> No.updateRange (f a) r)++updateRangeWithKeyAdjustT+  , updateRangeWithKeyDeleteT+ :: (Eq a, Integral a) => TreeT (Word, Word, a) a+updateRangeWithKeyAdjustT = updateRangeWithKeyT_ (\a k -> Just . (+ fromIntegral k) . (+ a))+updateRangeWithKeyDeleteT = updateRangeWithKeyT_ (\_ _ _ -> Nothing)++updateRangeWithKeyT_+  :: (Eq a, Integral a)+  => (a -> Word -> a -> Maybe a) -> TreeT (Word, Word, a) a+updateRangeWithKeyT_ f =+  Test treeEq (patRange $ \r a -> Pat.updateRangeWithKey (f a) r)+              (noRange $ \r a -> No.updateRangeWithKey (f a) r)++++takeRangeT :: Eq a => TreeT (Word, Word) a+takeRangeT = Test treeEq (patRange_ Pat.takeRange) (noRange_ No.takeRange)++++lookupMinT :: Eq a => IdT () a (Maybe a)+lookupMinT = Test (==) (\_ -> Pat.lookupMin) (\_ -> No.lookupMin)++lookupMinWithKeyT :: Eq a => LookupT () a+lookupMinWithKeyT = Test lookupEq (\_ -> Pat.lookupMinWithKey) (\_ -> No.lookupMinWithKey)++adjustMinT :: (Eq a, Integral a) => TreeT () a+adjustMinT = Test treeEq (\_ -> Pat.adjustMin (+ 10000)) (\_ -> No.adjustMin (+ 10000))++adjustMinWithKeyT :: (Eq a, Integral a) => TreeT () a+adjustMinWithKeyT =+  let f k = (+ fromIntegral k)+  in Test treeEq (\_ -> Pat.adjustMinWithKey f) (\_ -> No.adjustMinWithKey f)++deleteMinT :: (Eq a, Integral a) => TreeT () a+deleteMinT = Test treeEq (\_ -> Pat.deleteMin) (\_ -> No.deleteMin)++updateMinAdjustT, updateMinDeleteT :: (Eq a, Integral a) => TreeT () a+updateMinAdjustT = updateMinT_ (Just . (+ 10000))+updateMinDeleteT = updateMinT_ (\_ -> Nothing)++updateMinT_ :: (Eq a, Integral a) => (a -> Maybe a) -> TreeT () a+updateMinT_ f = Test treeEq (\_ -> Pat.updateMin f) (\_ -> No.updateMin f)++updateMinWithKeyAdjustT, updateMinWithKeyDeleteT :: (Eq a, Integral a) => TreeT () a+updateMinWithKeyAdjustT = updateMinWithKeyT_ (\k -> Just . (+ fromIntegral k))+updateMinWithKeyDeleteT = updateMinWithKeyT_ (\_ _ -> Nothing)++updateMinWithKeyT_ :: (Eq a, Integral a) => (Word -> a -> Maybe a) -> TreeT () a+updateMinWithKeyT_ f =+  Test treeEq (\_ -> Pat.updateMinWithKey f) (\_ -> No.updateMinWithKey f)++minViewT :: Eq a => MinViewT () a+minViewT = Test minViewEq (\_ -> Pat.minView) (\_ -> No.minView)++++lookupMaxT :: Eq a => IdT () a (Maybe a)+lookupMaxT = Test (==) (\_ -> Pat.lookupMax) (\_ -> No.lookupMax)++lookupMaxWithKeyT :: Eq a => LookupT () a+lookupMaxWithKeyT = Test lookupEq (\_ -> Pat.lookupMaxWithKey) (\_ -> No.lookupMaxWithKey)++adjustMaxT :: (Eq a, Integral a) => TreeT () a+adjustMaxT = Test treeEq (\_ -> Pat.adjustMax (+ 10000)) (\_ -> No.adjustMax (+ 10000))++adjustMaxWithKeyT :: (Eq a, Integral a) => TreeT () a+adjustMaxWithKeyT =+  let f k = (+ fromIntegral k)+  in Test treeEq (\_ -> Pat.adjustMaxWithKey f) (\_ -> No.adjustMaxWithKey f)++deleteMaxT :: (Eq a, Integral a) => TreeT () a+deleteMaxT = Test treeEq (\_ -> Pat.deleteMax) (\_ -> No.deleteMax)++updateMaxAdjustT, updateMaxDeleteT :: (Eq a, Integral a) => TreeT () a+updateMaxAdjustT = updateMaxT_ (Just . (+ 10000))+updateMaxDeleteT = updateMaxT_ (\_ -> Nothing)++updateMaxT_ :: (Eq a, Integral a) => (a -> Maybe a) -> TreeT () a+updateMaxT_ f = Test treeEq (\_ -> Pat.updateMax f) (\_ -> No.updateMax f)++updateMaxWithKeyAdjustT, updateMaxWithKeyDeleteT :: (Eq a, Integral a) => TreeT () a+updateMaxWithKeyAdjustT = updateMaxWithKeyT_ (\k -> Just . (+ fromIntegral k))+updateMaxWithKeyDeleteT = updateMaxWithKeyT_ (\_ _ -> Nothing)++updateMaxWithKeyT_ :: (Eq a, Integral a) => (Word -> a -> Maybe a) -> TreeT () a+updateMaxWithKeyT_ f =+  Test treeEq (\_ -> Pat.updateMaxWithKey f) (\_ -> No.updateMaxWithKey f)++maxViewT :: Eq a => MaxViewT () a+maxViewT = Test maxViewEq (\_ -> Pat.maxView) (\_ -> No.maxView)++++eqT :: (Eq a, Integral a) => IdT (Pat.Patricia a, NoTree Word a) a Bool+eqT = Test (==) (\(a, _) b -> a == b) (\(_, a) b -> a == b)++filterT :: (Eq a, Integral a) => TreeT () a+filterT = Test treeEq (\_ -> Pat.filter odd) (\_ -> No.filter odd)++filterWithKeyT :: (Eq a, Integral a) => TreeT () a+filterWithKeyT =+  let f k a = odd $ fromIntegral k + a+  in Test treeEq (\_ -> Pat.filterWithKey f) (\_ -> No.filterWithKey f)++mapMaybeT :: (Eq a, Integral a) => TreeT () a+mapMaybeT =+  let f a | odd a     = Nothing+          | otherwise = Just a++  in Test treeEq (\_ -> Pat.mapMaybe f) (\_ -> No.mapMaybe f)++mapMaybeWithKeyT :: (Eq a, Integral a) => TreeT () a+mapMaybeWithKeyT =+  let f k a | odd (fromIntegral k + a) = Nothing+            | otherwise                = Just a++  in Test treeEq (\_ -> Pat.mapMaybeWithKey f) (\_ -> No.mapMaybeWithKey f)++partitionT :: (Eq a, Integral a) => SplitT () a+partitionT = Test splitEq (\_ -> Pat.partition odd) (\_ -> No.partition odd)++partitionWithKeyT :: (Eq a, Integral a) => SplitT () a+partitionWithKeyT =+  let f k a = odd $ fromIntegral k + a+  in Test splitEq (\_ -> Pat.partitionWithKey f) (\_ -> No.partitionWithKey f)++mapEitherT :: (Eq a, Integral a) => SplitT () a+mapEitherT =+  let f a | odd a     = Left a+          | otherwise = Right a++  in Test splitEq (\_ -> Pat.mapEither f) (\_ -> No.mapEither f)++mapEitherWithKeyT :: (Eq a, Integral a) => SplitT () a+mapEitherWithKeyT =+  let f k a | odd (fromIntegral k + a) = Left a+            | otherwise                = Right a++  in Test splitEq (\_ -> Pat.mapEitherWithKey f) (\_ -> No.mapEitherWithKey f)++++mapT :: (Eq a, Num a) => TreeT () a+mapT =+  let f = (+ 10000)+  in Test treeEq (\_ -> Pat.map f) (\_ -> No.map f)++mapWithKeyT :: (Eq a, Num a) => TreeT () a+mapWithKeyT =+  let f k = (+ fromIntegral k) . (+ 10000)+  in Test treeEq (\_ -> Pat.mapWithKey f) (\_ -> No.mapWithKey f)++++sizeT :: IdT () a Int+sizeT = Test (==) (\_ -> Pat.size) (\_ -> No.size)++foldlT, foldlT' :: Eq a => IdT () a [a]+foldlT  = foldlT_ Pat.foldl+foldlT' = foldlT_ Pat.foldl'++foldlT_ :: Eq a => (forall x. (x -> a -> x) -> x -> Patricia a -> x) -> IdT () a [a]+foldlT_ g = Test (==) (\_ -> g (flip (:)) []) (\_ -> No.foldl (flip (:)) [])++foldlWithKeyT, foldlWithKeyT' :: Eq a => IdT () a [(Word, a)]+foldlWithKeyT  = foldlWithKeyT_ Pat.foldlWithKey+foldlWithKeyT' = foldlWithKeyT_ Pat.foldlWithKey'++foldlWithKeyT_+  :: Eq a+  => (forall x. (x -> Word -> a -> x) -> x -> Patricia a -> x) -> IdT () a [(Word, a)]+foldlWithKeyT_ g =+  let f z k a = (k, a) : z+  in Test (==) (\_ -> g f []) (\_ -> No.foldlWithKey f [])++++foldrT, foldrT' :: Eq a => IdT () a [a]+foldrT  = foldrT_ Pat.foldr+foldrT' = foldrT_ Pat.foldr'++foldrT_+  :: Eq a => (forall x. (a -> x -> x) -> x -> Patricia a -> x) -> IdT () a [a]+foldrT_ g = Test (==) (\_ -> g (:) []) (\_ -> No.foldr (:) [])++foldrWithKeyT, foldrWithKeyT' :: Eq a => IdT () a [(Word, a)]+foldrWithKeyT  = foldrWithKeyT_ Pat.foldrWithKey+foldrWithKeyT' = foldrWithKeyT_ Pat.foldrWithKey'++foldrWithKeyT_+  :: Eq a+  => (forall x. (Word -> a -> x -> x) -> x -> Patricia a -> x) -> IdT () a [(Word, a)]+foldrWithKeyT_ g =+  let f k a = (:) (k, a)+  in Test (==) (\_ -> g f []) (\_ -> No.foldrWithKey f [])++++foldMapT :: Eq a => IdT () a [a]+foldMapT = Test (==) (\_ -> Pat.foldMap pure) (\_ -> No.foldMap pure)++foldMapWithKeyT :: Eq a => IdT () a [(Word, a)]+foldMapWithKeyT =+  let f k a = [(k, a)]+  in Test (==) (\_ -> Pat.foldMapWithKey f) (\_ -> No.foldMapWithKey f)++++idTreeEq :: Eq a => Identity (Patricia a) -> Identity (NoTree Word a) -> Bool+idTreeEq (Identity a) (Identity b) = treeEq a b++traverseT+  :: (Eq a, Num a)+  => Test s (Patricia a) (NoTree Word a) (Identity (Patricia a)) (Identity (NoTree Word a))+traverseT =+  let f = Identity . (+ 10000)+  in Test idTreeEq (\_ -> Pat.traverse f) (\_ -> No.traverse f)++traverseWithKeyT+  :: (Eq a, Num a)+  => Test s (Patricia a) (NoTree Word a) (Identity (Patricia a)) (Identity (NoTree Word a))+traverseWithKeyT =+  let f k a = Identity $ fromIntegral k + 10000 + a+  in Test idTreeEq (\_ -> Pat.traverseWithKey f) (\_ -> No.traverseWithKey f)++++unionT :: Eq a => TreeT (Patricia a, NoTree Word a) a+unionT = Test treeEq (\(a, _) b -> Pat.union a b) (\(_, a) b -> No.unionL a b)++unionLT :: Eq a => TreeT (Patricia a, NoTree Word a) a+unionLT = Test treeEq (\(a, _) b -> Pat.unionL a b) (\(_, a) b -> No.unionL a b)++unionWithT :: (Eq a, Num a) => TreeT (Patricia a, NoTree Word a) a+unionWithT = Test treeEq (\(a, _) b -> Pat.unionWith (+) a b)+                         (\(_, a) b -> No.unionWithKey (\_ -> (+)) a b)++unionWithKeyT+  , mergeUnionT+ :: (Eq a, Num a) => TreeT (Patricia a, NoTree Word a) a+unionWithKeyT = unionWithKeyT_ Pat.unionWithKey+mergeUnionT    =+  unionWithKeyT_ $ \f ->+    Pat.merge+      (\k a b -> Pat.Tip k $ f k a b)+      Pat.Tip Pat.Bin Pat.Tip Pat.Bin++unionWithKeyT_+  :: (Eq a, Num a)+  => (forall x. (Word -> x -> x -> x) -> Patricia x -> Patricia x -> Patricia x)+  -> TreeT (Patricia a, NoTree Word a) a+unionWithKeyT_ g =+  let f k a b = fromIntegral k + a + b+  in Test treeEq (\(a, _) b -> g f a b)+                 (\(_, a) b -> No.unionWithKey f a b)++++differenceT :: Eq a => TreeT (Patricia a, NoTree Word a) a+differenceT = Test treeEq (\(a, _) b -> Pat.difference a b)+                          (\(_, a) b -> No.difference a b)++differenceWithT :: (Eq a, Integral a) => TreeT (Patricia a, NoTree Word a) a+differenceWithT =+  let f a b = let c = a + b+              in if odd c+                   then Nothing+                   else Just c++  in Test treeEq (\(a, _) b -> Pat.differenceWith f a b)+                 (\(_, a) b -> No.differenceWithKey (\_ -> f) a b)++differenceWithKeyT+  , mergeDifferenceT+ :: (Eq a, Integral a) => TreeT (Patricia a, NoTree Word a) a+differenceWithKeyT = differenceWithKeyT_ Pat.differenceWithKey+mergeDifferenceT    =+  differenceWithKeyT_ $ \f ->+    Pat.merge+      (\k a b -> case f k a b of+                   Just c  -> Pat.Tip k c+                   Nothing -> Pat.Nil+      )+      Pat.Tip Pat.Bin+      (\_ _ -> Pat.Nil) (\_ _ _ -> Pat.Nil)++differenceWithKeyT_+  :: (Eq a, Integral a)+  => (forall x y. (Word -> x -> y -> Maybe x) -> Patricia x -> Patricia y -> Patricia x)+  -> TreeT (Patricia a, NoTree Word a) a+differenceWithKeyT_ g =+  let f k a b = let c = fromIntegral k + a + b+                in if odd c+                     then Nothing+                     else Just c++  in Test treeEq (\(a, _) b -> g f a b)+                 (\(_, a) b -> No.differenceWithKey f a b)++++disjointT :: IdT (Patricia a, NoTree Word a) a Bool+disjointT = Test (==) (\(a, _) b -> Pat.disjoint a b)+                      (\(_, a) b -> No.null $ No.intersectionL a b)++intersectionT :: Eq a => TreeT (Patricia a, NoTree Word a) a+intersectionT = Test treeEq (\(a, _) b -> Pat.intersection a b)+                             (\(_, a) b -> No.intersectionL a b)++intersectionLT :: Eq a => TreeT (Patricia a, NoTree Word a) a+intersectionLT = Test treeEq (\(a, _) b -> Pat.intersectionL a b)+                             (\(_, a) b -> No.intersectionL a b)++intersectionWithT :: (Eq a, Num a) => TreeT (Patricia a, NoTree Word a) a+intersectionWithT = Test treeEq (\(a, _) b -> Pat.intersectionWith (+) a b)+                                (\(_, a) b -> No.intersectionWithKey (\_ -> (+)) a b)++intersectionWithKeyT+  , mergeIntersectionT+ :: (Eq a, Num a) => TreeT (Patricia a, NoTree Word a) a+intersectionWithKeyT = intersectionWithKeyT_ Pat.intersectionWithKey+mergeIntersectionT    =+  intersectionWithKeyT_ $ \f ->+    Pat.merge+      (\k a b -> Pat.Tip k $ f k a b)+      (\_ _ -> Pat.Nil) (\_ _ _ -> Pat.Nil)+      (\_ _ -> Pat.Nil) (\_ _ _ -> Pat.Nil)++intersectionWithKeyT_+  :: (Eq a, Num a)+  => (forall x y z. (Word -> x -> y -> z) -> Patricia x -> Patricia y -> Patricia z)+  -> TreeT (Patricia a, NoTree Word a) a+intersectionWithKeyT_ g =+  let f k a b = fromIntegral k + a + b+  in Test treeEq (\(a, _) b -> g f a b)+                 (\(_, a) b -> No.intersectionWithKey f a b)++++compareT :: Eq a => IdT (Patricia a, NoTree Word a) a Pat.PartialOrdering+compareT = Test (==) (\(a, _) b -> Pat.compare (==) a b)+                     (\(_, a) b -> No.compare a b)++++test :: Spec+test = do+  describe "Single-key" $ do+    it "lookup"           $ run unary1_ lookupT+    it "find"             $ run unary1  findT+    it "member"           $ run unary1_ memberT+    it "insert"           $ run unary1  insertT+    it "insertWith"       $ run unary1  insertWithT+    it "adjust"           $ run unary1  adjustT+    it "delete"           $ run unary1_ deleteT+    it "update/adjust"    $ run unary1  updateAdjustT+    it "update/delete"    $ run unary1  updateDeleteT+    it "alter/insert"     $ run unary1  alterInsertT+    it "alter/insertWith" $ run unary1  alterInsertWithT+    it "alter/adjust"     $ run unary1  alterAdjustT+    it "alter/delete"     $ run unary1  alterDeleteT++  describe "Split" $ do+    it "splitL"           $ run unary1_ splitLT+    it "splitR"           $ run unary1_ splitRT+    it "splitLookup"      $ run unary1_ splitLookupT++  describe "Left" $ do+    it "lookupL"               $ run unary1_ lookupLT+    it "adjustL"               $ run unary1  adjustLT+    it "adjustLWithKey"        $ run unary1  adjustLWithKeyT+    it "deleteL"               $ run unary1_ deleteLT+    it "updateL/adjust"        $ run unary1  updateLAdjustT+    it "updateL/delete"        $ run unary1  updateLDeleteT+    it "updateLWithKey/adjust" $ run unary1  updateLWithKeyAdjustT+    it "updateLWithKey/delete" $ run unary1  updateLWithKeyDeleteT+    it "takeL"                 $ run unary1_ takeLT++  describe "Right" $ do+    it "lookupR"               $ run unary1_ lookupRT+    it "adjustR"               $ run unary1  adjustRT+    it "adjustRWithKey"        $ run unary1  adjustRWithKeyT+    it "deleteR"               $ run unary1_ deleteRT+    it "updateR/adjust"        $ run unary1  updateRAdjustT+    it "updateR/delete"        $ run unary1  updateRDeleteT+    it "updateRWithKey/adjust" $ run unary1  updateRWithKeyAdjustT+    it "updateRWithKey/delete" $ run unary1  updateRWithKeyDeleteT+    it "takeR"                 $ run unary1_ takeRT++  describe "Range" $ do+    it "adjustRange"               $ run unary2  adjustRangeT+    it "adjustRangeWithKey"        $ run unary2  adjustRangeWithKeyT+    it "deleteRange"               $ run unary2_ deleteRangeT+    it "updateRange/adjust"        $ run unary2  updateRangeAdjustT+    it "updateRange/delete"        $ run unary2  updateRangeDeleteT+    it "updateRangeWithKey/adjust" $ run unary2  updateRangeWithKeyAdjustT+    it "updateRangeWithKey/delete" $ run unary2  updateRangeWithKeyDeleteT+    it "takeRange"                 $ run unary2_ takeRangeT++  describe "Min" $ do+    it "lookupMin"               $ run unary0 lookupMinT+    it "lookupMinWithKey"        $ run unary0 lookupMinWithKeyT+    it "adjustMin"               $ run unary0 adjustMinT+    it "adjustMinWithKey"        $ run unary0 adjustMinWithKeyT+    it "deleteMin"               $ run unary0 deleteMinT+    it "updateMin/adjust"        $ run unary0 updateMinAdjustT+    it "updateMin/delete"        $ run unary0 updateMinDeleteT+    it "updateMinWithKey/adjust" $ run unary0 updateMinWithKeyAdjustT+    it "updateMinWithKey/delete" $ run unary0 updateMinWithKeyDeleteT+    it "minView"                 $ run unary0 minViewT++  describe "Max" $ do+    it "lookupMax"               $ run unary0 lookupMaxT+    it "lookupMaxWithKey"        $ run unary0 lookupMaxWithKeyT+    it "adjustMax"               $ run unary0 adjustMaxT+    it "adjustMaxWithKey"        $ run unary0 adjustMaxWithKeyT+    it "deleteMax"               $ run unary0 deleteMaxT+    it "updateMax/adjust"        $ run unary0 updateMaxAdjustT+    it "updateMax/delete"        $ run unary0 updateMaxDeleteT+    it "updateMaxWithKey/adjust" $ run unary0 updateMaxWithKeyAdjustT+    it "updateMaxWithKey/delete" $ run unary0 updateMaxWithKeyDeleteT+    it "maxView"                 $ run unary0 maxViewT++  describe "Partition" $ do+    it "filter"           $ run unary0 filterT+    it "filterWithKey"    $ run unary0 filterWithKeyT+    it "mapMaybe"         $ run unary0 mapMaybeT+    it "mapMaybeWithKey"  $ run unary0 mapMaybeWithKeyT+    it "partition"        $ run unary0 partitionT+    it "partitionWithKey" $ run unary0 partitionWithKeyT+    it "mapEither"        $ run unary0 mapEitherT+    it "mapEitherWithKey" $ run unary0 mapEitherWithKeyT++  describe "Full-tree" $ do+    it "(==)"            $ run (equal <> binaryL) eqT+    it "map"             $ run unary0 mapT+    it "mapWithKey"      $ run unary0 mapWithKeyT+    it "size"            $ run unary0 sizeT+    it "foldl"           $ run unary0 foldlT+    it "foldl'"          $ run unary0 foldlT'+    it "foldlWithKey"    $ run unary0 foldlWithKeyT+    it "foldlWithKey'"   $ run unary0 foldlWithKeyT'+    it "foldr"           $ run unary0 foldrT+    it "foldr'"          $ run unary0 foldrT'+    it "foldrWithKey"    $ run unary0 foldrWithKeyT+    it "foldrWithKey'"   $ run unary0 foldrWithKeyT'+    it "foldMap"         $ run unary0 foldMapT+    it "foldMapWithKey"  $ run unary0 foldMapWithKeyT+    it "traverse"        $ run unary0 traverseT+    it "traverseWithKey" $ run unary0 traverseWithKeyT++  describe "Merge" $ do+    it "union"                $ run binary  unionT+    it "unionL"               $ run binaryL unionLT+    it "unionWith"            $ run binaryL unionWithT+    it "unionWithKey"         $ run binaryL unionWithKeyT+    it "difference"           $ run binaryL differenceT+    it "differenceWith"       $ run binaryL differenceWithT+    it "differenceWithKey"    $ run binaryL differenceWithKeyT+    it "disjoint/yes"         $ run binary  disjointT+    it "disjoint/no"          $ run binaryL disjointT+    it "intersection"         $ run binary  intersectionT+    it "intersectionL"        $ run binaryL intersectionLT+    it "intersectionWith"     $ run binaryL intersectionWithT+    it "intersectionWithKey"  $ run binaryL intersectionWithKeyT+    it "compare/subset"       $ run subset   compareT+    it "compare/superset"     $ run superset compareT+    it "compare/equal"        $ run equal    compareT+    it "compare/incomparable" $ run binary   compareT+    it "merge/union"          $ run binaryL mergeUnionT+    it "merge/difference"     $ run binaryL mergeDifferenceT+    it "merge/intersection"   $ run binaryL mergeIntersectionT
+ test/properties/Test/Patricia/Word/Sample.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE RankNTypes #-}++module Test.Patricia.Word.Sample+  ( Sample+  , zero+  , one+  , tiny+  , small+  , medium+  , large++  , mkUnary0+  , mkUnary1+  , mkUnary2++  , mkBinary+  , mkBinaryL++  , mkEqual+  , mkSuperset+  , mkSubset+  ) where++import           No.Tree (NoTree)+import qualified No.Tree as No+import           Test.Kit+import           Test.Random++import qualified Data.List as List+import           System.Random++++data Sample = Sample+                [(Word, Int)] -- ^ Keys in the dictionary+                [(Word, Int)] -- ^ Keys not in the dictionary+              deriving Show++zero, one :: Sample+zero = Sample [] [(4507, 1), (5824, 2), (6183, 3), (6858, 4)]+one  = Sample [(6593, 0)]+              [(4905, 1), (6285, 2), (6134, 3), (6737, 4), (6928, 5), (7513, 6)]++++halve :: [a] -> ([a], [a])+halve (a:b:cs) = let ~(xs, ys) = halve cs+                 in (a:xs, b:ys)+halve a        = (a, [])++sample :: (Word, Word) -> Int -> StdGen -> Sample+sample r n g =+  let ~(xs, _) = list (uniformR r) n g++      ~(ys, zs) = halve $ zip (List.nub xs) [0..]++  in Sample ys zs++tiny, small, medium, large :: Sample+tiny   = sample (0x1000, 0x80000) 8    (mkStdGen 0)+small  = sample (0x1000, 0x80000) 64   (mkStdGen 1)+medium = sample (0x1000, 0x80000) 512  (mkStdGen 2)+large  = sample (0x1000, 0x80000) 4096 (mkStdGen 3)++++type FromList pat = forall x. [(Word, x)] -> pat x++mkUnary0 :: FromList pat -> Sample -> [Case () (pat Int) (NoTree Word Int)]+mkUnary0 patFromList (Sample xs _) = [Case () (patFromList xs) (No.fromList xs)]++mkUnary1 :: FromList pat -> Sample -> [Case (Word, Int) (pat Int) (NoTree Word Int)]+mkUnary1 patFromList (Sample xs ys) =+  let pat = patFromList xs+      no  = No.fromList xs++  in foldr (\x -> (:) (Case x pat no)) [] $ xs <> ys++mkUnary2+  :: FromList pat -> Sample -> [Case (Word, Word, Int) (pat Int) (NoTree Word Int)]+mkUnary2 patFromList (Sample xs ys) =+  let pat = patFromList xs+      no  = No.fromList xs++      ~(as, bs) = halve xs+      ~(cs, ds) = halve ys++      ones = fmap (\(a, i) -> (a, a, i)) $ as <> cs++      twos = zipWith (\(a, i) (b, _) -> (a, b, i)) bs ds++  in foldr (\x -> (:) (Case x pat no)) [] $ ones <> twos+++mkBinary+  :: FromList pat+  -> Sample+  -> [Case (pat Int, NoTree Word Int) (pat Int) (NoTree Word Int)]+mkBinary patFromList (Sample xs ys) =+  [Case (patFromList ys, No.fromList ys) (patFromList xs) (No.fromList xs)]++mkBinaryL+  :: FromList pat+  -> Sample+  -> [Case (pat Int, NoTree Word Int) (pat Int) (NoTree Word Int)]+mkBinaryL patFromList (Sample xs ys) =+  let ~(as, _) = halve xs+      ~(bs, _) = halve ys++      ls = fmap (\(k, a) -> (k, negate a)) bs <> xs+      rs = fmap (\(k, a) -> (k, negate a)) as <> ys++  in [Case (patFromList rs, No.fromList rs) (patFromList ls) (No.fromList ls)]+++mkEqual+  :: FromList pat+  -> Sample+  -> [Case (pat Int, NoTree Word Int) (pat Int) (NoTree Word Int)]+mkEqual patFromList (Sample xs _) =+  let pat = patFromList xs+      no  = No.fromList xs++  in [Case (pat, no) pat no]++mkSuperset+  :: FromList pat+  -> Sample+  -> [Case (pat Int, NoTree Word Int) (pat Int) (NoTree Word Int)]+mkSuperset patFromList (Sample xs ys) =+  let zs = xs <> ys+  in [Case (patFromList zs, No.fromList zs) (patFromList xs) (No.fromList xs)]++mkSubset+  :: FromList pat+  -> Sample+  -> [Case (pat Int, NoTree Word Int) (pat Int) (NoTree Word Int)]+mkSubset patFromList (Sample xs ys) =+  let zs = xs <> ys+  in [Case (patFromList xs, No.fromList xs) (patFromList zs) (No.fromList zs)]
+ test/properties/Test/Patricia/Word/Strict.hs view
@@ -0,0 +1,907 @@+{-# LANGUAGE RankNTypes #-}++module Test.Patricia.Word.Strict+  ( test+  ) where++import           Data.Patricia.Word.Strict (Patricia)+import qualified Data.Patricia.Word.Strict as Pat+import           Data.Patricia.Word.Strict.Debug (validate, Validity (..))+import qualified Data.Patricia.Word.Strict.Unsafe as Pat+import           No.Tree (NoTree)+import qualified No.Tree as No+import           Test.Patricia.Word.Sample+import           Test.Kit++import           Data.Functor.Identity+import           Test.Hspec++++patFromList :: [(Word, a)] -> Patricia a+patFromList = foldr (\(k, a) p -> Pat.insert k a p) Pat.empty++patToList :: Patricia a -> [(Word, a)]+patToList = Pat.foldrWithKey (\k a -> (:) (k, a)) []++++patRange :: (Pat.Range -> a -> b) -> (Word, Word, a) -> b+patRange f (k1, k2, a) = f (Pat.Range k1 k2) a++patRange_ :: (Pat.Range -> b) -> (Word, Word) -> b+patRange_ f (k1, k2) = f (Pat.Range k1 k2)++noRange :: (No.Range Word -> a -> b) -> (Word, Word, a) -> b+noRange f (k1, k2, a) = f (No.WordRange No.Closed k1 No.Closed k2) a++noRange_ :: (No.Range Word -> b) -> (Word, Word) -> b+noRange_ f (k1, k2) = f (No.WordRange No.Closed k1 No.Closed k2)++++unary0 :: [Case () (Patricia Int) (NoTree Word Int)]+unary0 = foldMap (mkUnary0 patFromList) [zero, one, tiny, small, medium] -- , large]++unary1 :: [Case (Word, Int) (Patricia Int) (NoTree Word Int)]+unary1 = foldMap (mkUnary1 patFromList) [zero, one, tiny, small, medium] -- , large]++unary1_ :: [Case Word (Patricia Int) (NoTree Word Int)]+unary1_ = augment fst unary1++unary2 :: [Case (Word, Word, Int) (Patricia Int) (NoTree Word Int)]+unary2 = foldMap (mkUnary2 patFromList) [zero, one, tiny, small, medium] -- , large]++unary2_ :: [Case (Word, Word) (Patricia Int) (NoTree Word Int)]+unary2_ = augment (\(k1, k2, _) -> (k1, k2)) unary2++binary+  , binaryL+  , subset+  , superset+  , equal+ :: [Case (Patricia Int, NoTree Word Int) (Patricia Int) (NoTree Word Int)]+binary   = foldMap (mkBinary   patFromList) [zero, one, tiny, small, medium] -- , large]+binaryL  = foldMap (mkBinaryL  patFromList) [zero, one, tiny, small, medium] -- , large]+subset   = foldMap (mkSubset   patFromList) [zero, one, tiny, small, medium] -- , large]+superset = foldMap (mkSuperset patFromList) [zero, one, tiny, small, medium] -- , large]+equal    = foldMap (mkEqual    patFromList) [zero, one, tiny, small, medium] -- , large]++++type IdT s a b = Test s (Patricia a) (NoTree Word a) b b++type TreeT s a = Test s (Patricia a) (NoTree Word a) (Patricia a) (NoTree Word a)++treeEq :: Eq a => Patricia a -> NoTree Word a -> Bool+treeEq pat no =+  case validate pat of+    Valid -> patToList pat == No.toList no+    _     -> False++type SplitT s a =+       Test s (Patricia a) (NoTree Word a)+         (Pat.Split a a) (NoTree Word a, NoTree Word a)++splitEq+  :: Eq a => Pat.Split a a -> (NoTree Word a, NoTree Word a) -> Bool+splitEq (Pat.Split a b) (x, y) = treeEq a x && treeEq b y++type SplitLookupT s a =+       Test s (Patricia a) (NoTree Word a)+         (Pat.SplitLookup a a a) (NoTree Word a, Maybe a, NoTree Word a)++splitLookupEq+  :: Eq a+  => Pat.SplitLookup a a a -> (NoTree Word a, Maybe a, NoTree Word a) -> Bool+splitLookupEq (Pat.SplitLookup a b c) (x, y, z) = treeEq a x && b == y && treeEq c z++type LookupT s a =+       Test s (Patricia a) (NoTree Word a) (Maybe (Pat.Lookup a)) (Maybe (Word, a))++lookupEq :: Eq a => Maybe (Pat.Lookup a) -> Maybe (Word, a) -> Bool+lookupEq (Just (Pat.Lookup k a)) (Just (l, b)) = k == l && a == b+lookupEq Nothing                 Nothing       = True+lookupEq _                       _             = False++type MinViewT s a =+       Test s (Patricia a) (NoTree Word a)+         (Maybe (Pat.ViewL a)) (Maybe (Word, a, NoTree Word a))++minViewEq :: Eq a => Maybe (Pat.ViewL a) -> Maybe (Word, a, NoTree Word a) -> Bool+minViewEq (Just (Pat.ViewL (Pat.Lookup k a) pat)) (Just (l, b, no)) =+  k == l && a == b && treeEq pat no++minViewEq Nothing Nothing = True+minViewEq _       _       = False++type MaxViewT s a =+       Test s (Patricia a) (NoTree Word a)+         (Maybe (Pat.ViewR a)) (Maybe (NoTree Word a, Word, a))++maxViewEq :: Eq a => Maybe (Pat.ViewR a) -> Maybe (NoTree Word a, Word, a) -> Bool+maxViewEq (Just (Pat.ViewR pat (Pat.Lookup k a))) (Just (no, l, b)) =+  k == l && a == b && treeEq pat no++maxViewEq Nothing Nothing = True+maxViewEq _       _       = False++++lookupT, dirtyLookupT :: Eq a => IdT Word a (Maybe a)+lookupT      = lookupT_ Pat.lookup+dirtyLookupT = lookupT_ Pat.dirtyLookup++lookupT_ :: Eq a => (forall x. Word -> Patricia x -> Maybe x) -> IdT Word a (Maybe a)+lookupT_ f = Test (==) f No.lookup++findT, dirtyFindT :: Eq a => IdT (Word, a) a a+findT      = findT_ Pat.find+dirtyFindT = findT_ Pat.dirtyFind++findT_ :: Eq a => (forall x. x -> Word -> Patricia x -> x) -> IdT (Word, a) a a+findT_ f = Test (==) (\(k, a) -> f a k) (\(k, a) -> No.find a k)++memberT, dirtyMemberT :: IdT Word a Bool+memberT      = memberT_ Pat.member+dirtyMemberT = memberT_ Pat.dirtyMember++memberT_ :: (forall x. Word -> Patricia x -> Bool) -> IdT Word a Bool+memberT_ f = Test (==) f No.member++++insertT :: Eq a => TreeT (Word, a) a+insertT = Test treeEq (uncurry Pat.insert) (uncurry No.insert)++insertWithT, insertWithT' :: (Eq a, Integral a) => TreeT (Word, a) a+insertWithT  = insertWithT_ Pat.insertWith+insertWithT' = insertWithT_ Pat.insertWith'++insertWithT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Word -> x -> Patricia x -> Patricia x) -> TreeT (Word, a) a+insertWithT_ g =+  let f x = (+ fromIntegral x)+  in Test treeEq (\(k, a) -> g (f a) k a) (\(k, a) -> No.insertWith (f a) k a)++adjustT, adjustT' :: (Eq a, Integral a) => TreeT (Word, a) a+adjustT  = adjustT_ Pat.adjust+adjustT' = adjustT_ Pat.adjust'++adjustT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Word -> Patricia x -> Patricia x) -> TreeT (Word, a) a+adjustT_ g =+  let f a = (+ fromIntegral a)+  in Test treeEq (\(k, a) -> g (f a) k) (\(k, a) -> No.adjust (f a) k)++deleteT :: Eq a => TreeT Word a+deleteT = Test treeEq Pat.delete No.delete++updateAdjustT, updateDeleteT :: (Eq a, Integral a) => TreeT (Word, a) a+updateAdjustT = updateT_ (\a -> Just . (+ a))+updateDeleteT = updateT_ (\_ _ -> Nothing)++updateT_ :: Eq a => (a -> a -> Maybe a) -> TreeT (Word, a) a+updateT_ f = Test treeEq (\(k, a) -> Pat.update (f a) k) (\(k, a) -> No.update (f a) k)++alterInsertT+  , alterInsertWithT+  , alterAdjustT+  , alterDeleteT+ :: (Eq a, Integral a) => TreeT (Word, a) a+alterInsertT     = alterT_ (\a _ -> Just a)+alterInsertWithT = alterT_ (\a -> Just . maybe a (+ a))+alterAdjustT     = alterT_ (\a -> fmap (+ a))+alterDeleteT     = alterT_ (\_ _ -> Nothing)++alterT_ :: Eq a => (a -> Maybe a -> Maybe a) -> TreeT (Word, a) a+alterT_ f = Test treeEq (\(k, a) -> Pat.alter (f a) k) (\(k, a) -> No.alter (f a) k)++++splitLT :: Eq a => SplitT Word a+splitLT = Test splitEq Pat.splitL (No.splitL No.Closed)++splitRT :: Eq a => SplitT Word a+splitRT = Test splitEq Pat.splitR No.splitR++splitLookupT :: Eq a => SplitLookupT Word a+splitLookupT = Test splitLookupEq Pat.splitLookup No.splitLookup++++lookupLT :: Eq a => LookupT Word a+lookupLT = Test lookupEq Pat.lookupL (No.lookupL No.Closed)++adjustLT, adjustLT' :: (Eq a, Integral a) => TreeT (Word, a) a+adjustLT  = adjustLT_ Pat.adjustL+adjustLT' = adjustLT_ Pat.adjustL'++adjustLT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Word -> Patricia x -> Patricia x)+  -> TreeT (Word, a) a+adjustLT_ g =+  let f a = (+ a)+  in Test treeEq (\(k, a) -> g (f a) k) (\(k, a) -> No.adjustL (f a) No.Closed k)++adjustLWithKeyT+  , adjustLWithKeyT'+ :: (Eq a, Integral a) => TreeT (Word, a) a+adjustLWithKeyT  = adjustLWithKeyT_ Pat.adjustLWithKey+adjustLWithKeyT' = adjustLWithKeyT_ Pat.adjustLWithKey'++adjustLWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Word -> x -> x) -> Word -> Patricia x -> Patricia x)+  -> TreeT (Word, a) a+adjustLWithKeyT_ g =+  let f a k = (+ fromIntegral k) . (+ a)+  in Test treeEq (\(k, a) -> g (f a) k) (\(k, a) -> No.adjustLWithKey (f a) No.Closed k)++deleteLT :: Eq a => TreeT (Word) a+deleteLT = Test treeEq Pat.deleteL (No.deleteL No.Closed)++updateLAdjustT+  , updateLDeleteT+ :: (Eq a, Integral a) => TreeT (Word, a) a+updateLAdjustT = updateLT_ (\a -> Just . (+ a))+updateLDeleteT = updateLT_ (\_ _ -> Nothing)++updateLT_+  :: (Eq a, Integral a)+  => (a -> a -> Maybe a) -> TreeT (Word, a) a+updateLT_ f =+  Test treeEq (\(k, a) -> Pat.updateL (f a) k) (\(k, a) -> No.updateL (f a) No.Closed k)++updateLWithKeyAdjustT+  , updateLWithKeyDeleteT+ :: (Eq a, Integral a) => TreeT (Word, a) a+updateLWithKeyAdjustT = updateLWithKeyT_ (\a k -> Just . (+ fromIntegral k) . (+ a))+updateLWithKeyDeleteT = updateLWithKeyT_ (\_ _ _ -> Nothing)++updateLWithKeyT_+  :: (Eq a, Integral a)+  => (a -> Word -> a -> Maybe a) -> TreeT (Word, a) a+updateLWithKeyT_ f =+  Test treeEq (\(k, a) -> Pat.updateLWithKey (f a) k)+              (\(k, a) -> No.updateLWithKey (f a) No.Closed k)++takeLT :: Eq a => TreeT (Word) a+takeLT = Test treeEq Pat.takeL (No.takeL No.Closed)++++lookupRT :: Eq a => LookupT (Word) a+lookupRT = Test lookupEq Pat.lookupR (No.lookupR No.Closed)++adjustRT, adjustRT' :: (Eq a, Integral a) => TreeT (Word, a) a+adjustRT  = adjustRT_ Pat.adjustR+adjustRT' = adjustRT_ Pat.adjustR'++adjustRT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Word -> Patricia x -> Patricia x)+  -> TreeT (Word, a) a+adjustRT_ g =+  let f a = (+ a)+  in Test treeEq (\(k, a) -> g (f a) k) (\(k, a) -> No.adjustR (f a) No.Closed k)++adjustRWithKeyT+  , adjustRWithKeyT'+ :: (Eq a, Integral a) => TreeT (Word, a) a+adjustRWithKeyT  = adjustRWithKeyT_ Pat.adjustRWithKey+adjustRWithKeyT' = adjustRWithKeyT_ Pat.adjustRWithKey'++adjustRWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Word -> x -> x) -> Word -> Patricia x -> Patricia x)+  -> TreeT (Word, a) a+adjustRWithKeyT_ g =+  let f a k = (+ fromIntegral k) . (+ a)+  in Test treeEq (\(k, a) -> g (f a) k) (\(k, a) -> No.adjustRWithKey (f a) No.Closed k)++deleteRT :: Eq a => TreeT (Word) a+deleteRT = Test treeEq Pat.deleteR (No.deleteR No.Closed)++updateRAdjustT+  , updateRDeleteT+ :: (Eq a, Integral a) => TreeT (Word, a) a+updateRAdjustT = updateRT_ (\a -> Just . (+ a))+updateRDeleteT = updateRT_ (\_ _ -> Nothing)++updateRT_+  :: (Eq a, Integral a)+  => (a -> a -> Maybe a) -> TreeT (Word, a) a+updateRT_ f =+  Test treeEq (\(k, a) -> Pat.updateR (f a) k) (\(k, a) -> No.updateR (f a) No.Closed k)++updateRWithKeyAdjustT+  , updateRWithKeyDeleteT+ :: (Eq a, Integral a) => TreeT (Word, a) a+updateRWithKeyAdjustT = updateRWithKeyT_ (\a k -> Just . (+ fromIntegral k) . (+ a))+updateRWithKeyDeleteT = updateRWithKeyT_ (\_ _ _ -> Nothing)++updateRWithKeyT_+  :: (Eq a, Integral a)+  => (a -> Word -> a -> Maybe a) -> TreeT (Word, a) a+updateRWithKeyT_ f =+  Test treeEq (\(k, a) -> Pat.updateRWithKey (f a) k)+              (\(k, a) -> No.updateRWithKey (f a) No.Closed k)++takeRT :: Eq a => TreeT (Word) a+takeRT = Test treeEq Pat.takeR (No.takeR No.Closed)++++adjustRangeT+  , adjustRangeT'+ :: (Eq a, Integral a) => TreeT (Word, Word, a) a+adjustRangeT  = adjustRangeT_ Pat.adjustRange+adjustRangeT' = adjustRangeT_ Pat.adjustRange'++adjustRangeT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Pat.Range -> Patricia x -> Patricia x)+  -> TreeT (Word, Word, a) a+adjustRangeT_ g =+  let f a = (+ a)+  in Test treeEq (patRange $ \r a -> g (f a) r) (noRange $ \r a -> No.adjustRange (f a) r)++adjustRangeWithKeyT+  , adjustRangeWithKeyT'+ :: (Eq a, Integral a) => TreeT (Word, Word, a) a+adjustRangeWithKeyT  = adjustRangeWithKeyT_ Pat.adjustRangeWithKey+adjustRangeWithKeyT' = adjustRangeWithKeyT_ Pat.adjustRangeWithKey'++adjustRangeWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Word -> x -> x) -> Pat.Range -> Patricia x -> Patricia x)+  -> TreeT (Word, Word, a) a+adjustRangeWithKeyT_ g =+  let f a k = (+ fromIntegral k) . (+ a)+  in Test treeEq+       (patRange $ \r a -> g (f a) r) (noRange $ \r a -> No.adjustRangeWithKey (f a) r)++deleteRangeT :: Eq a => TreeT (Word, Word) a+deleteRangeT = Test treeEq (patRange_ Pat.deleteRange) (noRange_ No.deleteRange)++updateRangeAdjustT+  , updateRangeDeleteT+ :: (Eq a, Integral a) => TreeT (Word, Word, a) a+updateRangeAdjustT = updateRangeT_ (\a -> Just . (+ a))+updateRangeDeleteT = updateRangeT_ (\_ _ -> Nothing)++updateRangeT_+  :: (Eq a, Integral a)+  => (a -> a -> Maybe a) -> TreeT (Word, Word, a) a+updateRangeT_ f =+  Test treeEq+    (patRange $ \r a -> Pat.updateRange (f a) r) (noRange $ \r a -> No.updateRange (f a) r)++updateRangeWithKeyAdjustT+  , updateRangeWithKeyDeleteT+ :: (Eq a, Integral a) => TreeT (Word, Word, a) a+updateRangeWithKeyAdjustT = updateRangeWithKeyT_ (\a k -> Just . (+ fromIntegral k) . (+ a))+updateRangeWithKeyDeleteT = updateRangeWithKeyT_ (\_ _ _ -> Nothing)++updateRangeWithKeyT_+  :: (Eq a, Integral a)+  => (a -> Word -> a -> Maybe a) -> TreeT (Word, Word, a) a+updateRangeWithKeyT_ f =+  Test treeEq (patRange $ \r a -> Pat.updateRangeWithKey (f a) r)+              (noRange $ \r a -> No.updateRangeWithKey (f a) r)++++takeRangeT :: Eq a => TreeT (Word, Word) a+takeRangeT = Test treeEq (patRange_ Pat.takeRange) (noRange_ No.takeRange)++++lookupMinT :: Eq a => IdT () a (Maybe a)+lookupMinT = Test (==) (\_ -> Pat.lookupMin) (\_ -> No.lookupMin)++lookupMinWithKeyT :: Eq a => LookupT () a+lookupMinWithKeyT = Test lookupEq (\_ -> Pat.lookupMinWithKey) (\_ -> No.lookupMinWithKey)++adjustMinT, adjustMinT' :: (Eq a, Integral a) => TreeT () a+adjustMinT  = adjustMinT_ Pat.adjustMin+adjustMinT' = adjustMinT_ Pat.adjustMin'++adjustMinT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Patricia x -> Patricia x) -> TreeT () a+adjustMinT_ f = Test treeEq (\_ -> f (+ 10000)) (\_ -> No.adjustMin (+ 10000))++adjustMinWithKeyT, adjustMinWithKeyT' :: (Eq a, Integral a) => TreeT () a+adjustMinWithKeyT  = adjustMinWithKeyT_ Pat.adjustMinWithKey+adjustMinWithKeyT' = adjustMinWithKeyT_ Pat.adjustMinWithKey'++adjustMinWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Word -> x -> x) -> Patricia x -> Patricia x) -> TreeT () a+adjustMinWithKeyT_ g =+  let f k = (+ fromIntegral k)+  in Test treeEq (\_ -> g f) (\_ -> No.adjustMinWithKey f)++deleteMinT :: (Eq a, Integral a) => TreeT () a+deleteMinT = Test treeEq (\_ -> Pat.deleteMin) (\_ -> No.deleteMin)++updateMinAdjustT, updateMinDeleteT :: (Eq a, Integral a) => TreeT () a+updateMinAdjustT = updateMinT_ (Just . (+ 10000))+updateMinDeleteT = updateMinT_ (\_ -> Nothing)++updateMinT_ :: (Eq a, Integral a) => (a -> Maybe a) -> TreeT () a+updateMinT_ f = Test treeEq (\_ -> Pat.updateMin f) (\_ -> No.updateMin f)++updateMinWithKeyAdjustT, updateMinWithKeyDeleteT :: (Eq a, Integral a) => TreeT () a+updateMinWithKeyAdjustT = updateMinWithKeyT_ (\k -> Just . (+ fromIntegral k))+updateMinWithKeyDeleteT = updateMinWithKeyT_ (\_ _ -> Nothing)++updateMinWithKeyT_ :: (Eq a, Integral a) => (Word -> a -> Maybe a) -> TreeT () a+updateMinWithKeyT_ f =+  Test treeEq (\_ -> Pat.updateMinWithKey f) (\_ -> No.updateMinWithKey f)++minViewT :: Eq a => MinViewT () a+minViewT = Test minViewEq (\_ -> Pat.minView) (\_ -> No.minView)++++lookupMaxT :: Eq a => IdT () a (Maybe a)+lookupMaxT = Test (==) (\_ -> Pat.lookupMax) (\_ -> No.lookupMax)++lookupMaxWithKeyT :: Eq a => LookupT () a+lookupMaxWithKeyT = Test lookupEq (\_ -> Pat.lookupMaxWithKey) (\_ -> No.lookupMaxWithKey)++adjustMaxT, adjustMaxT' :: (Eq a, Integral a) => TreeT () a+adjustMaxT  = adjustMaxT_ Pat.adjustMax+adjustMaxT' = adjustMaxT_ Pat.adjustMax'++adjustMaxT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Patricia x -> Patricia x) -> TreeT () a+adjustMaxT_ f = Test treeEq (\_ -> f (+ 10000)) (\_ -> No.adjustMax (+ 10000))++adjustMaxWithKeyT, adjustMaxWithKeyT' :: (Eq a, Integral a) => TreeT () a+adjustMaxWithKeyT  = adjustMaxWithKeyT_ Pat.adjustMaxWithKey+adjustMaxWithKeyT' = adjustMaxWithKeyT_ Pat.adjustMaxWithKey'++adjustMaxWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Word -> x -> x) -> Patricia x -> Patricia x) -> TreeT () a+adjustMaxWithKeyT_ g =+  let f k = (+ fromIntegral k)+  in Test treeEq (\_ -> g f) (\_ -> No.adjustMaxWithKey f)++deleteMaxT :: (Eq a, Integral a) => TreeT () a+deleteMaxT = Test treeEq (\_ -> Pat.deleteMax) (\_ -> No.deleteMax)++updateMaxAdjustT, updateMaxDeleteT :: (Eq a, Integral a) => TreeT () a+updateMaxAdjustT = updateMaxT_ (Just . (+ 10000))+updateMaxDeleteT = updateMaxT_ (\_ -> Nothing)++updateMaxT_ :: (Eq a, Integral a) => (a -> Maybe a) -> TreeT () a+updateMaxT_ f = Test treeEq (\_ -> Pat.updateMax f) (\_ -> No.updateMax f)++updateMaxWithKeyAdjustT, updateMaxWithKeyDeleteT :: (Eq a, Integral a) => TreeT () a+updateMaxWithKeyAdjustT = updateMaxWithKeyT_ (\k -> Just . (+ fromIntegral k))+updateMaxWithKeyDeleteT = updateMaxWithKeyT_ (\_ _ -> Nothing)++updateMaxWithKeyT_ :: (Eq a, Integral a) => (Word -> a -> Maybe a) -> TreeT () a+updateMaxWithKeyT_ f =+  Test treeEq (\_ -> Pat.updateMaxWithKey f) (\_ -> No.updateMaxWithKey f)++maxViewT :: Eq a => MaxViewT () a+maxViewT = Test maxViewEq (\_ -> Pat.maxView) (\_ -> No.maxView)++++eqT :: (Eq a, Integral a) => IdT (Pat.Patricia a, No.NoTree Word a) a Bool+eqT = Test (==) (\(a, _) b -> a == b) (\(_, a) b -> a == b)++filterT :: (Eq a, Integral a) => TreeT () a+filterT = Test treeEq (\_ -> Pat.filter odd) (\_ -> No.filter odd)++filterWithKeyT :: (Eq a, Integral a) => TreeT () a+filterWithKeyT =+  let f k a = odd $ fromIntegral k + a+  in Test treeEq (\_ -> Pat.filterWithKey f) (\_ -> No.filterWithKey f)++mapMaybeT :: (Eq a, Integral a) => TreeT () a+mapMaybeT =+  let f a | odd a     = Nothing+          | otherwise = Just a++  in Test treeEq (\_ -> Pat.mapMaybe f) (\_ -> No.mapMaybe f)++mapMaybeWithKeyT :: (Eq a, Integral a) => TreeT () a+mapMaybeWithKeyT =+  let f k a | odd (fromIntegral k + a) = Nothing+            | otherwise                = Just a++  in Test treeEq (\_ -> Pat.mapMaybeWithKey f) (\_ -> No.mapMaybeWithKey f)++partitionT :: (Eq a, Integral a) => SplitT () a+partitionT = Test splitEq (\_ -> Pat.partition odd) (\_ -> No.partition odd)++partitionWithKeyT :: (Eq a, Integral a) => SplitT () a+partitionWithKeyT =+  let f k a = odd $ fromIntegral k + a+  in Test splitEq (\_ -> Pat.partitionWithKey f) (\_ -> No.partitionWithKey f)++mapEitherT :: (Eq a, Integral a) => SplitT () a+mapEitherT =+  let f a | odd a     = Left a+          | otherwise = Right a++  in Test splitEq (\_ -> Pat.mapEither f) (\_ -> No.mapEither f)++mapEitherWithKeyT :: (Eq a, Integral a) => SplitT () a+mapEitherWithKeyT =+  let f k a | odd (fromIntegral k + a) = Left a+            | otherwise                = Right a++  in Test splitEq (\_ -> Pat.mapEitherWithKey f) (\_ -> No.mapEitherWithKey f)++++mapT, mapT' :: (Eq a, Num a) => TreeT () a+mapT  = mapT_ Pat.map+mapT' = mapT_ Pat.map'++mapT_ :: (Eq a, Num a) => (forall x. (x -> x) -> Patricia x -> Patricia x) -> TreeT () a+mapT_ g =+  let f = (+ 10000)+  in Test treeEq (\_ -> g f) (\_ -> No.map f)++mapWithKeyT, mapWithKeyT' :: (Eq a, Num a) => TreeT () a+mapWithKeyT  = mapWithKeyT_ Pat.mapWithKey+mapWithKeyT' = mapWithKeyT_ Pat.mapWithKey'++mapWithKeyT_+  :: (Eq a, Num a)+  => (forall x. (Word -> x -> x) -> Patricia x -> Patricia x) -> TreeT () a+mapWithKeyT_ g =+  let f k = (+ fromIntegral k) . (+ 10000)+  in Test treeEq (\_ -> g f) (\_ -> No.mapWithKey f)++++sizeT :: IdT () a Int+sizeT = Test (==) (\_ -> Pat.size) (\_ -> No.size)++foldlT, foldlT' :: Eq a => IdT () a [a]+foldlT  = foldlT_ Pat.foldl+foldlT' = foldlT_ Pat.foldl'++foldlT_ :: Eq a => (forall x. (x -> a -> x) -> x -> Patricia a -> x) -> IdT () a [a]+foldlT_ g = Test (==) (\_ -> g (flip (:)) []) (\_ -> No.foldl (flip (:)) [])++foldlWithKeyT, foldlWithKeyT' :: Eq a => IdT () a [(Word, a)]+foldlWithKeyT  = foldlWithKeyT_ Pat.foldlWithKey+foldlWithKeyT' = foldlWithKeyT_ Pat.foldlWithKey'++foldlWithKeyT_+  :: Eq a+  => (forall x. (x -> Word -> a -> x) -> x -> Patricia a -> x) -> IdT () a [(Word, a)]+foldlWithKeyT_ g =+  let f z k a = (k, a) : z+  in Test (==) (\_ -> g f []) (\_ -> No.foldlWithKey f [])++++foldrT, foldrT' :: Eq a => IdT () a [a]+foldrT  = foldrT_ Pat.foldr+foldrT' = foldrT_ Pat.foldr'++foldrT_+  :: Eq a => (forall x. (a -> x -> x) -> x -> Patricia a -> x) -> IdT () a [a]+foldrT_ g = Test (==) (\_ -> g (:) []) (\_ -> No.foldr (:) [])++foldrWithKeyT, foldrWithKeyT' :: Eq a => IdT () a [(Word, a)]+foldrWithKeyT  = foldrWithKeyT_ Pat.foldrWithKey+foldrWithKeyT' = foldrWithKeyT_ Pat.foldrWithKey'++foldrWithKeyT_+  :: Eq a+  => (forall x. (Word -> a -> x -> x) -> x -> Patricia a -> x) -> IdT () a [(Word, a)]+foldrWithKeyT_ g =+  let f k a = (:) (k, a)+  in Test (==) (\_ -> g f []) (\_ -> No.foldrWithKey f [])++++foldMapT :: Eq a => IdT () a [a]+foldMapT = Test (==) (\_ -> Pat.foldMap pure) (\_ -> No.foldMap pure)++foldMapWithKeyT :: Eq a => IdT () a [(Word, a)]+foldMapWithKeyT =+  let f k a = [(k, a)]+  in Test (==) (\_ -> Pat.foldMapWithKey f) (\_ -> No.foldMapWithKey f)++++idTreeEq :: Eq a => Identity (Patricia a) -> Identity (NoTree Word a) -> Bool+idTreeEq (Identity a) (Identity b) = treeEq a b++traverseT+  :: (Eq a, Num a)+  => Test s (Patricia a) (NoTree Word a) (Identity (Patricia a)) (Identity (NoTree Word a))+traverseT =+  let f = Identity . (+ 10000)+  in Test idTreeEq (\_ -> Pat.traverse f) (\_ -> No.traverse f)++traverseWithKeyT+  :: (Eq a, Num a)+  => Test s (Patricia a) (NoTree Word a) (Identity (Patricia a)) (Identity (NoTree Word a))+traverseWithKeyT =+  let f k a = Identity $ fromIntegral k + 10000 + a+  in Test idTreeEq (\_ -> Pat.traverseWithKey f) (\_ -> No.traverseWithKey f)++++unionT :: Eq a => TreeT (Patricia a, NoTree Word a) a+unionT = Test treeEq (\(a, _) b -> Pat.union a b) (\(_, a) b -> No.unionL a b)++unionLT :: Eq a => TreeT (Patricia a, NoTree Word a) a+unionLT = Test treeEq (\(a, _) b -> Pat.unionL a b) (\(_, a) b -> No.unionL a b)++unionWithT' :: (Eq a, Num a) => TreeT (Patricia a, NoTree Word a) a+unionWithT' = Test treeEq (\(a, _) b -> Pat.unionWith' (+) a b)+                          (\(_, a) b -> No.unionWithKey (\_ -> (+)) a b)++unionWithKeyT'+  , mergeUnionT+ :: (Eq a, Num a) => TreeT (Patricia a, NoTree Word a) a+unionWithKeyT' = unionWithKeyT_ Pat.unionWithKey'+mergeUnionT    =+  unionWithKeyT_ $ \f ->+    Pat.merge+      (\k a b -> Pat.Tip k $ f k a b)+      Pat.Tip Pat.Bin Pat.Tip Pat.Bin++unionWithKeyT_+  :: (Eq a, Num a)+  => (forall x. (Word -> x -> x -> x) -> Patricia x -> Patricia x -> Patricia x)+  -> TreeT (Patricia a, NoTree Word a) a+unionWithKeyT_ g =+  let f k a b = fromIntegral k + a + b+  in Test treeEq (\(a, _) b -> g f a b)+                 (\(_, a) b -> No.unionWithKey f a b)++++differenceT :: Eq a => TreeT (Patricia a, NoTree Word a) a+differenceT = Test treeEq (\(a, _) b -> Pat.difference a b)+                          (\(_, a) b -> No.difference a b)++differenceWithT :: (Eq a, Integral a) => TreeT (Patricia a, NoTree Word a) a+differenceWithT =+  let f a b = let c = a + b+              in if odd c+                   then Nothing+                   else Just c++  in Test treeEq (\(a, _) b -> Pat.differenceWith f a b)+                 (\(_, a) b -> No.differenceWithKey (\_ -> f) a b)++differenceWithKeyT+  , mergeDifferenceT+ :: (Eq a, Integral a) => TreeT (Patricia a, NoTree Word a) a+differenceWithKeyT = differenceWithKeyT_ Pat.differenceWithKey+mergeDifferenceT    =+  differenceWithKeyT_ $ \f ->+    Pat.merge+      (\k a b -> case f k a b of+                   Just c  -> Pat.Tip k c+                   Nothing -> Pat.Nil+      )+      Pat.Tip Pat.Bin+      (\_ _ -> Pat.Nil) (\_ _ _ -> Pat.Nil)++differenceWithKeyT_+  :: (Eq a, Integral a)+  => (forall x y. (Word -> x -> y -> Maybe x) -> Patricia x -> Patricia y -> Patricia x)+  -> TreeT (Patricia a, NoTree Word a) a+differenceWithKeyT_ g =+  let f k a b = let c = fromIntegral k + a + b+                in if odd c+                     then Nothing+                     else Just c++  in Test treeEq (\(a, _) b -> g f a b)+                 (\(_, a) b -> No.differenceWithKey f a b)++++disjointT :: IdT (Patricia a, NoTree Word a) a Bool+disjointT = Test (==) (\(a, _) b -> Pat.disjoint a b)+                      (\(_, a) b -> No.null $ No.intersectionL a b)++intersectionT :: Eq a => TreeT (Patricia a, NoTree Word a) a+intersectionT = Test treeEq (\(a, _) b -> Pat.intersection a b)+                             (\(_, a) b -> No.intersectionL a b)++intersectionLT :: Eq a => TreeT (Patricia a, NoTree Word a) a+intersectionLT = Test treeEq (\(a, _) b -> Pat.intersectionL a b)+                             (\(_, a) b -> No.intersectionL a b)++intersectionWithT' :: (Eq a, Num a) => TreeT (Patricia a, NoTree Word a) a+intersectionWithT' = Test treeEq (\(a, _) b -> Pat.intersectionWith' (+) a b)+                                 (\(_, a) b -> No.intersectionWithKey (\_ -> (+)) a b)++intersectionWithKeyT'+  , mergeIntersectionT+ :: (Eq a, Num a) => TreeT (Patricia a, NoTree Word a) a+intersectionWithKeyT' = intersectionWithKeyT_ Pat.intersectionWithKey'+mergeIntersectionT    =+  intersectionWithKeyT_ $ \f ->+    Pat.merge+      (\k a b -> Pat.Tip k $ f k a b)+      (\_ _ -> Pat.Nil) (\_ _ _ -> Pat.Nil)+      (\_ _ -> Pat.Nil) (\_ _ _ -> Pat.Nil)++intersectionWithKeyT_+  :: (Eq a, Num a)+  => (forall x y z. (Word -> x -> y -> z) -> Patricia x -> Patricia y -> Patricia z)+  -> TreeT (Patricia a, NoTree Word a) a+intersectionWithKeyT_ g =+  let f k a b = fromIntegral k + a + b+  in Test treeEq (\(a, _) b -> g f a b)+                 (\(_, a) b -> No.intersectionWithKey f a b)++++compareT :: Eq a => IdT (Patricia a, NoTree Word a) a Pat.PartialOrdering+compareT = Test (==) (\(a, _) b -> Pat.compare (==) a b)+                     (\(_, a) b -> No.compare a b)++++test :: Spec+test = do+  describe "Single-key" $ do+    it "lookup"           $ run unary1_ lookupT+    it "dirtyLookup"      $ run unary1_ dirtyLookupT+    it "find"             $ run unary1  findT+    it "dirtyFind"        $ run unary1  dirtyFindT+    it "member"           $ run unary1_ memberT+    it "dirtyMember"      $ run unary1_ dirtyMemberT+    it "insert"           $ run unary1  insertT+    it "insertWith"       $ run unary1  insertWithT+    it "insertWith'"      $ run unary1  insertWithT'+    it "adjust"           $ run unary1  adjustT+    it "adjust'"          $ run unary1  adjustT'+    it "delete"           $ run unary1_ deleteT+    it "update/adjust"    $ run unary1  updateAdjustT+    it "update/delete"    $ run unary1  updateDeleteT+    it "alter/insert"     $ run unary1  alterInsertT+    it "alter/insertWith" $ run unary1  alterInsertWithT+    it "alter/adjust"     $ run unary1  alterAdjustT+    it "alter/delete"     $ run unary1  alterDeleteT++  describe "Split" $ do+    it "splitL"           $ run unary1_ splitLT+    it "splitR"           $ run unary1_ splitRT+    it "splitLookup"      $ run unary1_ splitLookupT++  describe "Left" $ do+    it "lookupL"               $ run unary1_ lookupLT+    it "adjustL"               $ run unary1  adjustLT+    it "adjustL'"              $ run unary1  adjustLT'+    it "adjustLWithKey"        $ run unary1  adjustLWithKeyT+    it "adjustLWithKey'"       $ run unary1  adjustLWithKeyT'+    it "deleteL"               $ run unary1_ deleteLT+    it "updateL/adjust"        $ run unary1  updateLAdjustT+    it "updateL/delete"        $ run unary1  updateLDeleteT+    it "updateLWithKey/adjust" $ run unary1  updateLWithKeyAdjustT+    it "updateLWithKey/delete" $ run unary1  updateLWithKeyDeleteT+    it "takeL"                 $ run unary1_ takeLT++  describe "Right" $ do+    it "lookupR"               $ run unary1_ lookupRT+    it "adjustR"               $ run unary1  adjustRT+    it "adjustR'"              $ run unary1  adjustRT'+    it "adjustRWithKey"        $ run unary1  adjustRWithKeyT+    it "adjustRWithKey'"       $ run unary1  adjustRWithKeyT'+    it "deleteR"               $ run unary1_ deleteRT+    it "updateR/adjust"        $ run unary1  updateRAdjustT+    it "updateR/delete"        $ run unary1  updateRDeleteT+    it "updateRWithKey/adjust" $ run unary1  updateRWithKeyAdjustT+    it "updateRWithKey/delete" $ run unary1  updateRWithKeyDeleteT+    it "takeR"                 $ run unary1_ takeRT++  describe "Range" $ do+    it "adjustRange"               $ run unary2  adjustRangeT+    it "adjustRange'"              $ run unary2  adjustRangeT'+    it "adjustRangeWithKey"        $ run unary2  adjustRangeWithKeyT+    it "adjustRangeWithKey'"       $ run unary2  adjustRangeWithKeyT'+    it "deleteRange"               $ run unary2_ deleteRangeT+    it "updateRange/adjust"        $ run unary2  updateRangeAdjustT+    it "updateRange/delete"        $ run unary2  updateRangeDeleteT+    it "updateRangeWithKey/adjust" $ run unary2  updateRangeWithKeyAdjustT+    it "updateRangeWithKey/delete" $ run unary2  updateRangeWithKeyDeleteT+    it "takeRange"                 $ run unary2_ takeRangeT++  describe "Min" $ do+    it "lookupMin"               $ run unary0 lookupMinT+    it "lookupMinWithKey"        $ run unary0 lookupMinWithKeyT+    it "adjustMin"               $ run unary0 adjustMinT+    it "adjustMinWithKey"        $ run unary0 adjustMinWithKeyT+    it "adjustMin'"              $ run unary0 adjustMinT'+    it "adjustMinWithKey'"       $ run unary0 adjustMinWithKeyT'+    it "deleteMin"               $ run unary0 deleteMinT+    it "updateMin/adjust"        $ run unary0 updateMinAdjustT+    it "updateMin/delete"        $ run unary0 updateMinDeleteT+    it "updateMinWithKey/adjust" $ run unary0 updateMinWithKeyAdjustT+    it "updateMinWithKey/delete" $ run unary0 updateMinWithKeyDeleteT+    it "minView"                 $ run unary0 minViewT++  describe "Max" $ do+    it "lookupMax"               $ run unary0 lookupMaxT+    it "lookupMaxWithKey"        $ run unary0 lookupMaxWithKeyT+    it "adjustMax"               $ run unary0 adjustMaxT+    it "adjustMaxWithKey"        $ run unary0 adjustMaxWithKeyT+    it "adjustMax'"              $ run unary0 adjustMaxT'+    it "adjustMaxWithKey'"       $ run unary0 adjustMaxWithKeyT'+    it "deleteMax"               $ run unary0 deleteMaxT+    it "updateMax/adjust"        $ run unary0 updateMaxAdjustT+    it "updateMax/delete"        $ run unary0 updateMaxDeleteT+    it "updateMaxWithKey/adjust" $ run unary0 updateMaxWithKeyAdjustT+    it "updateMaxWithKey/delete" $ run unary0 updateMaxWithKeyDeleteT+    it "maxView"                 $ run unary0 maxViewT++  describe "Partition" $ do+    it "filter"           $ run unary0 filterT+    it "filterWithKey"    $ run unary0 filterWithKeyT+    it "mapMaybe"         $ run unary0 mapMaybeT+    it "mapMaybeWithKey"  $ run unary0 mapMaybeWithKeyT+    it "partition"        $ run unary0 partitionT+    it "partitionWithKey" $ run unary0 partitionWithKeyT+    it "mapEither"        $ run unary0 mapEitherT+    it "mapEitherWithKey" $ run unary0 mapEitherWithKeyT++  describe "Full-tree" $ do+    it "(==)"            $ run (equal <> binaryL) eqT+    it "map"             $ run unary0 mapT+    it "map'"            $ run unary0 mapT'+    it "mapWithKey"      $ run unary0 mapWithKeyT+    it "mapWithKey'"     $ run unary0 mapWithKeyT'+    it "size"            $ run unary0 sizeT+    it "foldl"           $ run unary0 foldlT+    it "foldl'"          $ run unary0 foldlT'+    it "foldlWithKey"    $ run unary0 foldlWithKeyT+    it "foldlWithKey'"   $ run unary0 foldlWithKeyT'+    it "foldr"           $ run unary0 foldrT+    it "foldr'"          $ run unary0 foldrT'+    it "foldrWithKey"    $ run unary0 foldrWithKeyT+    it "foldrWithKey'"   $ run unary0 foldrWithKeyT'+    it "foldMap"         $ run unary0 foldMapT+    it "foldMapWithKey"  $ run unary0 foldMapWithKeyT+    it "traverse"        $ run unary0 traverseT+    it "traverseWithKey" $ run unary0 traverseWithKeyT++  describe "Merge" $ do+    it "union"                $ run binary  unionT+    it "unionL"               $ run binaryL unionLT+    it "unionWith'"           $ run binaryL unionWithT'+    it "unionWithKey'"        $ run binaryL unionWithKeyT'+    it "difference"           $ run binaryL differenceT+    it "differenceWith"       $ run binaryL differenceWithT+    it "differenceWithKey"    $ run binaryL differenceWithKeyT+    it "disjoint/yes"         $ run binary  disjointT+    it "disjoint/no"          $ run binaryL disjointT+    it "intersection"         $ run binary  intersectionT+    it "intersectionL"        $ run binaryL intersectionLT+    it "intersectionWith'"    $ run binaryL intersectionWithT'+    it "intersectionWithKey'" $ run binaryL intersectionWithKeyT'+    it "compare/subset"       $ run subset   compareT+    it "compare/superset"     $ run superset compareT+    it "compare/equal"        $ run equal    compareT+    it "compare/incomparable" $ run binary   compareT+    it "merge/union"          $ run binaryL mergeUnionT+    it "merge/difference"     $ run binaryL mergeDifferenceT+    it "merge/intersection"   $ run binaryL mergeIntersectionT
+ test/properties/Test/RadixNTree/Word8/Key.hs view
@@ -0,0 +1,154 @@+{-# LANGUAGE BangPatterns+           , OverloadedLists+           , OverloadedStrings #-}++module Test.RadixNTree.Word8.Key+  ( test+  ) where++import           Data.RadixTree.Word8.Key        as Radix+import           Data.RadixTree.Word8.Key.Unsafe as Radix+import           Data.Radix1Tree.Word8.Key        as Radix1+import           Data.Radix1Tree.Word8.Key.Unsafe as Radix1++import qualified Data.ByteString.Lazy.Internal as LazyBS (ByteString (..))+import           Data.String+import           Data.List.NonEmpty (NonEmpty (..))+import qualified Data.Primitive.ByteArray as Prim+import qualified Data.Text.Array as Array+import qualified Data.Text.Internal as Strict (Text (..))+import qualified Data.Text.Internal.Lazy as LazyText (Text (..))+import           Data.Word+import           Test.Hspec++++buildRef :: Build+buildRef = Build (Snoc (Snoc (Snoc Lin [0xC2]) [0xA3, 0x24, 0xE2]) [0x82, 0xAC])++buildRef1 :: Build1+buildRef1 = Build1 $ ((\(Build x) -> x) buildRef) :/ [0xC2, 0xA4]++++rawRef, rawRef1, utf8Ref, utf8Ref1 :: IsString a => a+rawRef   = "\xC2\xA3$\xE2\x82\xAC"+rawRef1  = "\xC2\xA3$\xE2\x82\xAC\xC2\xA4"+utf8Ref  = "£$€"+utf8Ref1 = "£$€¤"++++feedRef :: [Word8]+feedRef = [0xC2, 0xA3, 0x24, 0xE2, 0x82, 0xAC]++feedRef1 :: NonEmpty Word8+feedRef1 = 0xC2 :| [0xA3, 0x24, 0xE2, 0x82, 0xAC, 0xC2, 0xA4]++destroy :: Feed -> [Word8]+destroy (Feed feed) =+  feed $ \step ->++    let go s =+          case step s of+            More w s' -> w : go s'+            Done      -> []++    in go++destroy1 :: Feed1 -> NonEmpty Word8+destroy1 (Feed1 w feed) = w :| destroy (Feed feed)++++test :: Spec+test = do+  describe "build" $ do+    it "bytes" $+      Radix.buildBytes buildRef `shouldBe` feedRef++    it "bytes/1" $+      Radix1.buildBytes buildRef1 `shouldBe` feedRef1++    it "ByteString" $+      Radix.buildByteString buildRef `shouldBe` rawRef++    it "ByteString/1" $+      Radix1.buildByteString buildRef1 `shouldBe` rawRef1++    it "ShortByteString" $+      Radix.buildShortByteString buildRef `shouldBe` rawRef++    it "ShortByteString/1" $+      Radix1.buildShortByteString buildRef1 `shouldBe` rawRef1++    it "Text" $+      Radix.unsafeBuildText buildRef `shouldBe` utf8Ref++    it "Text/1" $+      Radix1.unsafeBuildText buildRef1 `shouldBe` utf8Ref1++  describe "feed" $ do+    it "bytes" $+      destroy (Radix.feedBytes feedRef) `shouldBe` feedRef++    it "bytes/1" $+      destroy1 (Radix1.feedBytes feedRef1) `shouldBe` feedRef1++    it "ByteString" $+      destroy (Radix.feedByteString rawRef) `shouldBe` feedRef++    it "ByteString/1" $+      destroy1 (Radix1.unsafeFeedByteString rawRef1) `shouldBe` feedRef1++    it "ShortByteString" $+      destroy (Radix.feedShortByteString rawRef) `shouldBe` feedRef++    it "ShortByteString/1" $+      destroy1 (Radix1.unsafeFeedShortByteString rawRef1) `shouldBe` feedRef1++    it "Text" $+      destroy (Radix.feedText utf8Ref) `shouldBe` feedRef++    it "Text/1" $+      destroy1 (Radix1.unsafeFeedText utf8Ref1) `shouldBe` feedRef1++    it "lazy ByteString" $+      let ref = LazyBS.Chunk [0xC2] . LazyBS.Chunk [0xA3, 0x24, 0xE2]+              $ LazyBS.Chunk [0x82, 0xAC] LazyBS.Empty++      in destroy (Radix.feedLazyByteString ref) `shouldBe` feedRef++    it "lazy ByteString/1" $+      let rest = LazyBS.Chunk [0xA3, 0x24, 0xE2]+               . LazyBS.Chunk [0x82, 0xAC]+               $ LazyBS.Chunk [0xC2, 0xA4] LazyBS.Empty++      in destroy1 (Radix1.unsafeFeedLazyByteString "\xC2" rest) `shouldBe` feedRef1++    it "lazy Text" $+      let !(Prim.ByteArray c1) = [0xC2]+          !(Prim.ByteArray c2) = [0xA3, 0x24, 0xE2]+          !(Prim.ByteArray c3) = [0x82, 0xAC]++          ref = LazyText.Chunk (Strict.Text (Array.ByteArray c1) 0 1)+              . LazyText.Chunk (Strict.Text (Array.ByteArray c2) 0 3)+              . LazyText.Chunk (Strict.Text (Array.ByteArray c3) 0 2)+              $ LazyText.Empty++      in destroy (Radix.feedLazyText ref) `shouldBe` feedRef++    it "lazy Text/1" $+      let !(Prim.ByteArray c1) = [0xC2]+          !(Prim.ByteArray c2) = [0xA3, 0x24, 0xE2]+          !(Prim.ByteArray c3) = [0x82, 0xAC]+          !(Prim.ByteArray c4) = [0xC2, 0xA4]++          first = Strict.Text (Array.ByteArray c1) 0 1++          ref = LazyText.Chunk (Strict.Text (Array.ByteArray c2) 0 3)+              . LazyText.Chunk (Strict.Text (Array.ByteArray c3) 0 2)+              . LazyText.Chunk (Strict.Text (Array.ByteArray c4) 0 2)+              $ LazyText.Empty++      in destroy1 (Radix1.unsafeFeedLazyText first ref) `shouldBe` feedRef1
+ test/properties/Test/RadixNTree/Word8/Sample.hs view
@@ -0,0 +1,268 @@+{-# LANGUAGE RankNTypes #-}++module Test.RadixNTree.Word8.Sample+  ( Sample+  , zero+  , one+  , tip+  , bin+  , tiny+  , small+  , medium+--, large++  , mkUnary0+  , mkUnary1+  , mkUnary2++  , mkBinary+  , mkBinaryL++  , mkEqual+  , mkSuperset+  , mkSubset+  ) where++import           No.Tree (NoTree)+import qualified No.Tree as No+import           Test.Kit+import           Test.Random++import           Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NonEmpty+import           Data.Word+import           System.Random++++data Trees = Trees (NonEmpty Tree)+           | End+             deriving Show++data Tree = Tree+              (NonEmpty Word8)+              Bool             -- ^ Whether this point is a separate key in the tree+              Trees+            deriving Show++++genTrees+  :: RandomGen g+  => Int         -- ^ Maximum branches on each level+  -> Int         -- ^ Maximum number of segments+  -> Int         -- ^ Maximum segment length+  -> Int         -- ^ Maximum total length+  -> g+  -> (Trees, g)+genTrees nB nL nS nT = broad nL nT+  where+    broad count len g0+      | len <= 0 || count <= 0 = (End, g0)+      | otherwise              =+          let ~(n, g1) = uniformR (1, nB) g0++              ~(as, g2) = list1 (deep count len) n g1++          in (Trees $ dedup as, g2)++    dedup = NonEmpty.nubBy (\(Tree (x :| _) _ _) (Tree (y :| _) _ _) -> x == y)++    deep count len g0 =+      let ~(n, g1) = uniformR (1, max 1 (min len nS)) g0++          ~(xs, g2) = list1 uniform n g1++          ~(t, g3) = broad (count - 1) (len - n) g2++          ~(bias, g4) = case t of+                          End -> (nL, g3)+                          _   -> uniformR (1, nL) g3++      in (Tree xs (bias == 1) t, g4)++++timber :: Trees -> [([Word8], Int)]+timber = fst . broad id ([], 1)+  where+    broad pre ~(acc, n) End        = ((pre [], n) : acc, n + 1)+    broad pre z         (Trees ts) = foldr (flip $ deep pre) z ts++    deep pre z@(acc, n) (Tree xs real t) =+      let z' = if real+                 then ((pre $ NonEmpty.toList xs, n) : acc, n + 1)+                 else z++      in broad (pre . (NonEmpty.toList xs <>)) z' t++++data Sample = Sample+                [(No.Openness, [Word8], Int)] -- ^ Keys in the dictionary+                [(No.Openness, [Word8], Int)] -- ^ Keys not in the dictionary+              deriving Show++halve :: [a] -> ([a], [a])+halve (a:b:cs) = let ~(xs, ys) = halve cs+                 in (a:xs, b:ys)+halve a        = (a, [])++sample :: RandomGen g => Trees -> g -> Sample+sample t g0 =+  let ~(xs, g1) = shuffle (timber t) g0++      ~(os, g2) = list (\g' -> let ~(b, g'') = uniform g'+                               in ( if b then No.Open else No.Closed+                                  , g''+                                  )+                       )+                       (length xs) g1++      xs' = zipWith (\a (b, c) -> (a, b, c)) os xs++      ~(ys, zs) = halve xs'++      ~(z, _) = uniform g2++      as | z         = case ys of+                         []               -> []+                         (b, _, i) : rest -> (b, [], i) : rest+         | otherwise = ys++      bs = case zs of+             []               -> []+             (b, _, i) : rest -> (b, [], i) : rest++  in Sample as bs++++zero, one, tip, bin :: Sample+zero = Sample []+         [ (No.Open, [], 1), (No.Closed, [1, 2, 3], 2), (No.Open, [3, 2, 1], 3) ]++one  = Sample [(No.Open, [1, 2, 3], 0)]+         [ (No.Closed, [1, 2, 3], 1), (No.Open, [1, 2, 2], 2), (No.Closed, [1, 2, 4], 3)+         , (No.Open, [1, 2], 4), (No.Closed, [1, 2, 3, 4], 5), (No.Open, [2, 3, 4], 6)+         , (No.Closed, [], 7), (No.Open, [2], 8)+         ]++tip  = Sample [(No.Open, [], 0)]+         [ (No.Closed, [1, 2, 3], 1), (No.Closed, [], 2) ]++bin  = Sample [(No.Open, [1, 2, 2, 3], 0), (No.Closed, [1, 2, 4, 5], 1)]+         [ (No.Closed, [1, 2, 3, 4], 2), (No.Open, [1, 2, 2, 3], 3)+         , (No.Closed, [1, 2, 4, 5], 4), (No.Closed, [], 5)+         ]++++tiny, small, medium :: Sample+tiny   = uncurry sample $ genTrees 4 2 4 16 (mkStdGen 2)+small  = uncurry sample $ genTrees 4 4 4 16 (mkStdGen 4)+medium = uncurry sample $ genTrees 8 4 4 16 (mkStdGen 16)++++type FromList pat = forall x. [([Word8], x)] -> pat x++mkUnary0 :: FromList pat -> Sample -> [Case () (pat Int) (NoTree [Word8] Int)]+mkUnary0 patFromList (Sample xs _) =+  let as = fmap (\(_, k, i) -> (k, i)) xs++  in [Case () (patFromList as) (No.fromList as)]++mkUnary1+  :: FromList pat+  -> Sample -> [Case (No.Openness, [Word8], Int) (pat Int) (NoTree [Word8] Int)]+mkUnary1 patFromList (Sample xs ys) =+  let as = fmap (\(_, k, i) -> (k, i)) xs++      pat = patFromList as+      no  = No.fromList as++  in foldr (\x -> (:) (Case x pat no)) [] $ xs <> ys++mkUnary2+  :: FromList pat+  -> Sample+  -> [Case (No.Openness, [Word8], No.Openness, [Word8], Int) (pat Int) (NoTree [Word8] Int)]+mkUnary2 patFromList (Sample xs ys) =+  let xs' = fmap (\(_, k, i) -> (k, i)) xs++      pat = patFromList xs'+      no  = No.fromList xs'++      ~(as, bs) = halve xs+      ~(cs, ds) = halve ys++      ones = fmap (\(o, a, i) -> (o, a, o, a, i)) $ as <> cs++      twos = zipWith (\(o, a, i) (p, b, _) -> (o, a, p, b, i)) bs ds++  in foldr (\x -> (:) (Case x pat no)) [] $ ones <> twos++++mkBinary+  :: FromList pat+  -> Sample+  -> [Case (pat Int, NoTree [Word8] Int) (pat Int) (NoTree [Word8] Int)]+mkBinary patFromList (Sample xs ys) =+  let as = fmap (\(_, k, i) -> (k, i)) xs+      bs = fmap (\(_, k, i) -> (k, i)) ys++  in [Case (patFromList bs, No.fromList bs) (patFromList as) (No.fromList as)]++mkBinaryL+  :: FromList pat+  -> Sample+  -> [Case (pat Int, NoTree [Word8] Int) (pat Int) (NoTree [Word8] Int)]+mkBinaryL patFromList (Sample xs ys) =+  let xs' = fmap (\(_, k, i) -> (k, i)) xs+      ys' = fmap (\(_, k, i) -> (k, i)) ys++      ~(as, _) = halve xs'+      ~(bs, _) = halve ys'++      ls = fmap (\(k, a) -> (k, negate a)) bs <> xs'+      rs = fmap (\(k, a) -> (k, negate a)) as <> ys'++  in [Case (patFromList rs, No.fromList rs) (patFromList ls) (No.fromList ls)]++mkEqual+  :: FromList pat+  -> Sample+  -> [Case (pat Int, NoTree [Word8] Int) (pat Int) (NoTree [Word8] Int)]+mkEqual patFromList (Sample xs _) =+  let as = fmap (\(_, k, i) -> (k, i)) xs++      pat = patFromList as+      no  = No.fromList as++  in [Case (pat, no) pat no]++mkSuperset+  :: FromList pat+  -> Sample+  -> [Case (pat Int, NoTree [Word8] Int) (pat Int) (NoTree [Word8] Int)]+mkSuperset patFromList (Sample xs ys) =+  let as = fmap (\(_, k, i) -> (k, i)) xs+      bs = fmap (\(_, k, i) -> (k, i)) ys++      zs = as <> bs++  in [Case (patFromList zs, No.fromList zs) (patFromList as) (No.fromList as)]++mkSubset+  :: FromList pat+  -> Sample+  -> [Case (pat Int, NoTree [Word8] Int) (pat Int) (NoTree [Word8] Int)]+mkSubset patFromList (Sample xs ys) =+  let as = fmap (\(_, k, i) -> (k, i)) xs+      bs = fmap (\(_, k, i) -> (k, i)) ys++      zs = as <> bs++  in [Case (patFromList as, No.fromList as) (patFromList zs) (No.fromList zs)]
+ test/properties/Test/RadixTree/Word8/Lazy.hs view
@@ -0,0 +1,820 @@+{-# LANGUAGE RankNTypes #-}++module Test.RadixTree.Word8.Lazy+  ( test+  ) where++import qualified Data.Radix1Tree.Word8.Lazy as Radix1+import           Data.RadixTree.Word8.Lazy (RadixTree)+import qualified Data.RadixTree.Word8.Lazy as Radix+import           Data.RadixTree.Word8.Lazy.Debug+import qualified Data.RadixTree.Word8.Lazy.Unsafe as Radix+import           No.Tree (NoTree)+import qualified No.Tree as No+import           Test.Kit+import           Test.RadixNTree.Word8.Sample++import           Data.Functor.Identity+import qualified Data.List as List+import           Data.Word+import           Test.Hspec++++radixFromList :: [([Word8], a)] -> RadixTree a+radixFromList = foldr (\(k, a) p -> Radix.insert (Radix.feedBytes k) a p) Radix.empty++radixToList :: RadixTree a -> [([Word8], a)]+radixToList = Radix.foldrWithKey (\k a -> (:) (Radix.buildBytes k, a)) []++++unary0 :: [Case () (RadixTree Int) (NoTree [Word8] Int)]+unary0 = foldMap (mkUnary0 radixFromList) [zero, one, tip, bin, tiny, small, medium]++unary1F :: [Case (No.Openness, [Word8], Int) (RadixTree Int) (NoTree [Word8] Int)]+unary1F = foldMap (mkUnary1 radixFromList) [zero, one, tip, bin, tiny, small, medium]++unary1R :: [Case (No.Openness, [Word8]) (RadixTree Int) (NoTree [Word8] Int)]+unary1R = augment (\(o, k, _) -> (o, k)) unary1F++unary1 :: [Case ([Word8], Int) (RadixTree Int) (NoTree [Word8] Int)]+unary1 = augment (\(_, k, i) -> (k, i)) unary1F++unary1_ :: [Case [Word8] (RadixTree Int) (NoTree [Word8] Int)]+unary1_ = augment (\(_, k, _) -> k) unary1F++++binary :: [Case (RadixTree Int, NoTree [Word8] Int) (RadixTree Int) (NoTree [Word8] Int)]+binary = foldMap (mkBinary radixFromList) [zero, one, tip, bin, tiny, small, medium]++binaryL :: [Case (RadixTree Int, NoTree [Word8] Int) (RadixTree Int) (NoTree [Word8] Int)]+binaryL = foldMap (mkBinaryL radixFromList) [zero, one, tip, bin, tiny, small, medium]++equal :: [Case (RadixTree Int, NoTree [Word8] Int) (RadixTree Int) (NoTree [Word8] Int)]+equal = foldMap (mkEqual radixFromList) [zero, one, tip, bin, tiny, small, medium]++subset :: [Case (RadixTree Int, NoTree [Word8] Int) (RadixTree Int) (NoTree [Word8] Int)]+subset = foldMap (mkSubset radixFromList) [zero, one, tip, bin, tiny, small, medium]++superset :: [Case (RadixTree Int, NoTree [Word8] Int) (RadixTree Int) (NoTree [Word8] Int)]+superset = foldMap (mkSuperset radixFromList) [zero, one, tip, bin, tiny, small, medium]++++type IdT s a b = Test s (RadixTree a) (NoTree [Word8] a) b b++type TreeT s a = Test s (RadixTree a) (NoTree [Word8] a) (RadixTree a) (NoTree [Word8] a)++treeEq :: Eq a => RadixTree a -> NoTree [Word8] a -> Bool+treeEq pat no =+  case validate pat of+    Valid -> radixToList pat == No.toList no+    _     -> False++type SplitT s a =+       Test s (RadixTree a) (NoTree [Word8] a)+         (RadixTree a, RadixTree a) (NoTree [Word8] a, NoTree [Word8] a)++splitEq+  :: Eq a => (RadixTree a, RadixTree a) -> (NoTree [Word8] a, NoTree [Word8] a) -> Bool+splitEq (a, b) (x, y) = treeEq a x && treeEq b y++type SplitLookupT s a =+       Test s (RadixTree a) (NoTree [Word8] a)+         (RadixTree a, Maybe a, RadixTree a) (NoTree [Word8] a, Maybe a, NoTree [Word8] a)++splitLookupEq+  :: Eq a+  => (RadixTree a, Maybe a, RadixTree a)+  -> (NoTree [Word8] a, Maybe a, NoTree [Word8] a) -> Bool+splitLookupEq (a, b, c) (x, y, z) = treeEq a x && b == y && treeEq c z++type LookupT s a =+       Test s (RadixTree a) (NoTree [Word8] a)+       (Maybe (Radix.Lookup a)) (Maybe ([Word8], a))++lookupEq :: Eq a => Maybe (Radix.Lookup a) -> Maybe ([Word8], a) -> Bool+lookupEq (Just (Radix.Lookup k a)) (Just (l, b)) = Radix.buildBytes k == l && a == b+lookupEq Nothing                   Nothing       = True+lookupEq _                         _             = False++type MinViewT s a =+       Test s (RadixTree a) (NoTree [Word8] a)+         (Maybe (Radix.ViewL a)) (Maybe ([Word8], a, NoTree [Word8] a))++minViewEq :: Eq a => Maybe (Radix.ViewL a) -> Maybe ([Word8], a, NoTree [Word8] a) -> Bool+minViewEq (Just (Radix.ViewL k a t)) (Just (l, b, no)) =+  Radix.buildBytes k == l && a == b && treeEq t no++minViewEq Nothing                    Nothing           = True+minViewEq _                          _                 = False++type MaxViewT s a =+       Test s (RadixTree a) (NoTree [Word8] a)+         (Maybe (Radix.ViewR a)) (Maybe (NoTree [Word8] a, [Word8], a))++maxViewEq :: Eq a => Maybe (Radix.ViewR a) -> Maybe (NoTree [Word8] a, [Word8], a) -> Bool+maxViewEq (Just (Radix.ViewR t k a)) (Just (no, l, b)) =+  Radix.buildBytes k == l && a == b && treeEq t no++maxViewEq Nothing                    Nothing           = True+maxViewEq _                          _                 = False++++lookupT :: Eq a => IdT [Word8] a (Maybe a)+lookupT = Test (==) (Radix.lookup . Radix.feedBytes) No.lookup++findT :: Eq a => IdT ([Word8], a) a a+findT = Test (==) (\(k, i) -> Radix.find i $ Radix.feedBytes k) (\(k, i) -> No.find i k)++memberT :: Eq a => IdT [Word8] a Bool+memberT = Test (==) (Radix.member . Radix.feedBytes) No.member++subtreeT :: Eq a => TreeT [Word8] a+subtreeT = Test treeEq (Radix.subtree . Radix.feedBytes) No.subtree++moveSingleT :: Eq a => IdT [Word8] a (Maybe a)+moveSingleT =+  Test (==) (\k -> Radix.stop . Radix.move (Radix.feedBytes k) . Radix.cursor)+            No.lookup++moveThirdsT :: Eq a => IdT [Word8] a (Maybe a)+moveThirdsT =+  let thirds xs = let len = length xs+                      ~(as, ys) = List.splitAt (len `quot` 3) xs+                      ~(bs, cs) = List.splitAt (len `quot` 3) ys++                  in Radix.move (Radix.feedBytes cs)+                   . Radix.move (Radix.feedBytes bs)+                   . Radix.move (Radix.feedBytes as)++  in Test (==) (\k -> Radix.stop . thirds k . Radix.cursor) No.lookup++++prefixT :: Eq a => TreeT [Word8] a+prefixT = Test treeEq (Radix.prefix . Radix.feedBytes) No.prefix++insertT :: Eq a => TreeT ([Word8], a) a+insertT = Test treeEq (\(k, i) -> Radix.insert (Radix.feedBytes k) i) (uncurry No.insert)++insertWithT :: (Eq a, Integral a) => TreeT ([Word8], a) a+insertWithT  = insertWithT_ Radix.insertWith++insertWithT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Radix.Feed -> x -> RadixTree x -> RadixTree x) -> TreeT ([Word8], a) a+insertWithT_ g =+  let f x = (+ fromIntegral x)+  in Test treeEq (\(k, a) -> g (f a) (Radix.feedBytes k) a)+                 (\(k, a) -> No.insertWith (f a) k a)++adjustT :: (Eq a, Integral a) => TreeT ([Word8], a) a+adjustT  = adjustT_ Radix.adjust++adjustT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Radix.Feed -> RadixTree x -> RadixTree x) -> TreeT ([Word8], a) a+adjustT_ g =+  let f a = (+ fromIntegral a)+  in Test treeEq (\(k, a) -> g (f a) (Radix.feedBytes k))+                 (\(k, a) -> No.adjust (f a) k)++deleteT :: Eq a => TreeT [Word8] a+deleteT = Test treeEq (Radix.delete . Radix.feedBytes) No.delete++pruneT :: Eq a => TreeT (No.Openness, [Word8]) a+pruneT = Test treeEq (\(o, k) -> Radix.prune o $ Radix.feedBytes k) (uncurry No.prune)++updateAdjustT, updateDeleteT :: (Eq a, Integral a) => TreeT ([Word8], a) a+updateAdjustT = updateT_ (\a -> Just . (+ a))+updateDeleteT = updateT_ (\_ _ -> Nothing)++updateT_ :: Eq a => (a -> a -> Maybe a) -> TreeT ([Word8], a) a+updateT_ f = Test treeEq (\(k, a) -> Radix.update (f a) (Radix.feedBytes k))+                         (\(k, a) -> No.update (f a) k)++alterInsertT+  , alterInsertWithT+  , alterAdjustT+  , alterDeleteT+ :: (Eq a, Integral a) => TreeT ([Word8], a) a+alterInsertT     = alterT_ (\a _ -> Just a)+alterInsertWithT = alterT_ (\a -> Just . maybe a (+ a))+alterAdjustT     = alterT_ (\a -> fmap (+ a))+alterDeleteT     = alterT_ (\_ _ -> Nothing)++alterT_ :: Eq a => (a -> Maybe a -> Maybe a) -> TreeT ([Word8], a) a+alterT_ f = Test treeEq (\(k, a) -> Radix.alter (f a) (Radix.feedBytes k))+                        (\(k, a) -> No.alter (f a) k)++shapeInsertT :: (Eq a, Integral a) => TreeT [Word8] a+shapeInsertT =+  Test treeEq+    (Radix.shape (Radix.insert (Radix.feedBytes [1, 2, 3]) 10000) . Radix.feedBytes)+    (No.shape (No.insert [1, 2, 3] 10000))++shapeAdjustT :: (Eq a, Integral a) => TreeT [Word8] a+shapeAdjustT = Test treeEq (Radix.shape (Radix.map negate) . Radix.feedBytes)+                           (No.shape (No.map negate))++shapeFilterT :: (Eq a, Integral a) => TreeT [Word8] a+shapeFilterT = Test treeEq (Radix.shape (Radix.filter odd) . Radix.feedBytes)+                           (No.shape (No.filter odd))++shapeDeleteT :: (Eq a, Integral a) => TreeT [Word8] a+shapeDeleteT = Test treeEq (Radix.shape (\_ -> Radix.empty) . Radix.feedBytes)+                           (No.shape (\_ -> No.empty))++++splitLT :: Eq a => SplitT (No.Openness, [Word8]) a+splitLT = Test splitEq (\(o, k) -> Radix.splitL o $ Radix.feedBytes k) (uncurry No.splitL)++splitLookupT :: Eq a => SplitLookupT [Word8] a+splitLookupT = Test splitLookupEq (Radix.splitLookup . Radix.feedBytes) No.splitLookup++++lookupLT :: Eq a => LookupT (No.Openness, [Word8]) a+lookupLT = Test lookupEq (\(o, k) -> Radix.lookupL o $ Radix.feedBytes k)+                         (uncurry No.lookupL)++adjustLT :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+adjustLT  = adjustLT_ Radix.adjustL++adjustLT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> No.Openness -> Radix.Feed -> RadixTree x -> RadixTree x)+  -> TreeT (No.Openness, [Word8], a) a+adjustLT_ g =+  let f a = (+ a)+  in Test treeEq (\(o, k, a) -> g (f a) o $ Radix.feedBytes k)+                 (\(o, k, a) -> No.adjustL (f a) o k)++adjustLWithKeyT :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+adjustLWithKeyT  = adjustLWithKeyT_ Radix.adjustLWithKey++adjustLWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Radix.Build -> x -> x) -> No.Openness -> Radix.Feed -> RadixTree x -> RadixTree x)+  -> TreeT (No.Openness, [Word8], a) a+adjustLWithKeyT_ g =+  let f a k = (+ sum (fmap fromIntegral k)) . (+ a)+  in Test treeEq (\(o, k, a) -> g (f a . Radix.buildBytes) o $ Radix.feedBytes k)+                 (\(o, k, a) -> No.adjustLWithKey (f a) o k)++updateLAdjustT+  , updateLDeleteT+ :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+updateLAdjustT = updateLT_ (\a -> Just . (+ a))+updateLDeleteT = updateLT_ (\_ _ -> Nothing)++updateLT_+  :: (Eq a, Integral a)+  => (a -> a -> Maybe a) -> TreeT (No.Openness, [Word8], a) a+updateLT_ f =+  Test treeEq (\(o, k, a) -> Radix.updateL (f a) o $ Radix.feedBytes k)+              (\(o, k, a) -> No.updateL (f a) o k)++updateLWithKeyAdjustT+  , updateLWithKeyDeleteT+ :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+updateLWithKeyAdjustT = updateLWithKeyT_ (\a k -> Just . (+ sum (fmap fromIntegral k)) . (+ a))+updateLWithKeyDeleteT = updateLWithKeyT_ (\_ _ _ -> Nothing)++updateLWithKeyT_+  :: (Eq a, Integral a)+  => (a -> [Word8] -> a -> Maybe a) -> TreeT (No.Openness, [Word8], a) a+updateLWithKeyT_ f =+  Test treeEq (\(o, k, a) -> Radix.updateLWithKey (f a . Radix.buildBytes) o $ Radix.feedBytes k)+              (\(o, k, a) -> No.updateLWithKey (f a) o k)++takeLT :: Eq a => TreeT (No.Openness, [Word8]) a+takeLT = Test treeEq (\(o, k) -> Radix.takeL o $ Radix.feedBytes k)+                     (uncurry No.takeL)++++lookupRT :: Eq a => LookupT (No.Openness, [Word8]) a+lookupRT = Test lookupEq (\(o, k) -> Radix.lookupR o $ Radix.feedBytes k)+                         (uncurry No.lookupR)++adjustRT :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+adjustRT  = adjustRT_ Radix.adjustR++adjustRT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> No.Openness -> Radix.Feed -> RadixTree x -> RadixTree x)+  -> TreeT (No.Openness, [Word8], a) a+adjustRT_ g =+  let f a = (+ a)+  in Test treeEq (\(o, k, a) -> g (f a) o $ Radix.feedBytes k)+                 (\(o, k, a) -> No.adjustR (f a) o k)++adjustRWithKeyT :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+adjustRWithKeyT  = adjustRWithKeyT_ Radix.adjustRWithKey++adjustRWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Radix.Build -> x -> x) -> No.Openness -> Radix.Feed -> RadixTree x -> RadixTree x)+  -> TreeT (No.Openness, [Word8], a) a+adjustRWithKeyT_ g =+  let f a k = (+ sum (fmap fromIntegral k)) . (+ a)+  in Test treeEq (\(o, k, a) -> g (f a . Radix.buildBytes) o $ Radix.feedBytes k)+                 (\(o, k, a) -> No.adjustRWithKey (f a) o k)++updateRAdjustT+  , updateRDeleteT+ :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+updateRAdjustT = updateRT_ (\a -> Just . (+ a))+updateRDeleteT = updateRT_ (\_ _ -> Nothing)++updateRT_+  :: (Eq a, Integral a)+  => (a -> a -> Maybe a) -> TreeT (No.Openness, [Word8], a) a+updateRT_ f =+  Test treeEq (\(o, k, a) -> Radix.updateR (f a) o $ Radix.feedBytes k)+              (\(o, k, a) -> No.updateR (f a) o k)++updateRWithKeyAdjustT+  , updateRWithKeyDeleteT+ :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+updateRWithKeyAdjustT = updateRWithKeyT_ (\a k -> Just . (+ sum (fmap fromIntegral k)) . (+ a))+updateRWithKeyDeleteT = updateRWithKeyT_ (\_ _ _ -> Nothing)++updateRWithKeyT_+  :: (Eq a, Integral a)+  => (a -> [Word8] -> a -> Maybe a) -> TreeT (No.Openness, [Word8], a) a+updateRWithKeyT_ f =+  Test treeEq (\(o, k, a) -> Radix.updateRWithKey (f a . Radix.buildBytes) o $ Radix.feedBytes k)+              (\(o, k, a) -> No.updateRWithKey (f a) o k)++takeRT :: Eq a => TreeT (No.Openness, [Word8]) a+takeRT = Test treeEq (\(o, k) -> Radix.takeR o $ Radix.feedBytes k)+                     (uncurry No.takeR)++++lookupMinT :: Eq a => IdT () a (Maybe a)+lookupMinT = Test (==) (\_ -> Radix.lookupMin) (\_ -> No.lookupMin)++lookupMinWithKeyT :: Eq a => LookupT () a+lookupMinWithKeyT =+  Test lookupEq (\_ -> Radix.lookupMinWithKey) (\_ -> No.lookupMinWithKey)++adjustMinT :: (Eq a, Integral a) => TreeT () a+adjustMinT  = adjustMinT_ Radix.adjustMin++adjustMinT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+adjustMinT_ f = Test treeEq (\_ -> f (+ 10000)) (\_ -> No.adjustMin (+ 10000))++adjustMinWithKeyT :: (Eq a, Integral a) => TreeT () a+adjustMinWithKeyT  = adjustMinWithKeyT_ Radix.adjustMinWithKey++adjustMinWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Radix.Build -> x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+adjustMinWithKeyT_ g =+  let f k = (+ sum (fmap fromIntegral k))+  in Test treeEq (\_ -> g (f . Radix.buildBytes)) (\_ -> No.adjustMinWithKey f)++deleteMinT :: (Eq a, Integral a) => TreeT () a+deleteMinT = Test treeEq (\_ -> Radix.deleteMin) (\_ -> No.deleteMin)++updateMinAdjustT, updateMinDeleteT :: (Eq a, Integral a) => TreeT () a+updateMinAdjustT = updateMinT_ (Just . (+ 10000))+updateMinDeleteT = updateMinT_ (\_ -> Nothing)++updateMinT_ :: (Eq a, Integral a) => (a -> Maybe a) -> TreeT () a+updateMinT_ f = Test treeEq (\_ -> Radix.updateMin f) (\_ -> No.updateMin f)++updateMinWithKeyAdjustT, updateMinWithKeyDeleteT :: (Eq a, Integral a) => TreeT () a+updateMinWithKeyAdjustT = updateMinWithKeyT_ (\k -> Just . (+ sum (fmap fromIntegral k)))+updateMinWithKeyDeleteT = updateMinWithKeyT_ (\_ _ -> Nothing)++updateMinWithKeyT_ :: (Eq a, Integral a) => ([Word8] -> a -> Maybe a) -> TreeT () a+updateMinWithKeyT_ f =+  Test treeEq (\_ -> Radix.updateMinWithKey (f . Radix.buildBytes))+              (\_ -> No.updateMinWithKey f)++minViewT :: Eq a => MinViewT () a+minViewT = Test minViewEq (\_ -> Radix.minView) (\_ -> No.minView)++++lookupMaxT :: Eq a => IdT () a (Maybe a)+lookupMaxT = Test (==) (\_ -> Radix.lookupMax) (\_ -> No.lookupMax)++lookupMaxWithKeyT :: Eq a => LookupT () a+lookupMaxWithKeyT =+  Test lookupEq (\_ -> Radix.lookupMaxWithKey) (\_ -> No.lookupMaxWithKey)++adjustMaxT :: (Eq a, Integral a) => TreeT () a+adjustMaxT  = adjustMaxT_ Radix.adjustMax++adjustMaxT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+adjustMaxT_ f = Test treeEq (\_ -> f (+ 10000)) (\_ -> No.adjustMax (+ 10000))++adjustMaxWithKeyT :: (Eq a, Integral a) => TreeT () a+adjustMaxWithKeyT  = adjustMaxWithKeyT_ Radix.adjustMaxWithKey++adjustMaxWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Radix.Build -> x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+adjustMaxWithKeyT_ g =+  let f k = (+ sum (fmap fromIntegral k))+  in Test treeEq (\_ -> g (f . Radix.buildBytes)) (\_ -> No.adjustMaxWithKey f)++deleteMaxT :: (Eq a, Integral a) => TreeT () a+deleteMaxT = Test treeEq (\_ -> Radix.deleteMax) (\_ -> No.deleteMax)++updateMaxAdjustT, updateMaxDeleteT :: (Eq a, Integral a) => TreeT () a+updateMaxAdjustT = updateMaxT_ (Just . (+ 10000))+updateMaxDeleteT = updateMaxT_ (\_ -> Nothing)++updateMaxT_ :: (Eq a, Integral a) => (a -> Maybe a) -> TreeT () a+updateMaxT_ f = Test treeEq (\_ -> Radix.updateMax f) (\_ -> No.updateMax f)++updateMaxWithKeyAdjustT, updateMaxWithKeyDeleteT :: (Eq a, Integral a) => TreeT () a+updateMaxWithKeyAdjustT = updateMaxWithKeyT_ (\k -> Just . (+ sum (fmap fromIntegral k)))+updateMaxWithKeyDeleteT = updateMaxWithKeyT_ (\_ _ -> Nothing)++updateMaxWithKeyT_ :: (Eq a, Integral a) => ([Word8] -> a -> Maybe a) -> TreeT () a+updateMaxWithKeyT_ f =+  Test treeEq (\_ -> Radix.updateMaxWithKey (f . Radix.buildBytes))+              (\_ -> No.updateMaxWithKey f)++maxViewT :: Eq a => MaxViewT () a+maxViewT = Test maxViewEq (\_ -> Radix.maxView) (\_ -> No.maxView)++++filterT :: (Eq a, Integral a) => TreeT () a+filterT = Test treeEq (\_ -> Radix.filter odd) (\_ -> No.filter odd)++filterWithKeyT :: (Eq a, Integral a) => TreeT () a+filterWithKeyT =+  let f k a = odd $ sum (fmap fromIntegral k) + a+  in Test treeEq (\_ -> Radix.filterWithKey (f . Radix.buildBytes))+                 (\_ -> No.filterWithKey f)++mapMaybeT :: (Eq a, Integral a) => TreeT () a+mapMaybeT =+  let f a | odd a     = Nothing+          | otherwise = Just a++  in Test treeEq (\_ -> Radix.mapMaybe f) (\_ -> No.mapMaybe f)++mapMaybeWithKeyT :: (Eq a, Integral a) => TreeT () a+mapMaybeWithKeyT =+  let f k a | odd (sum (fmap fromIntegral k) + a) = Nothing+            | otherwise                           = Just a++  in Test treeEq (\_ -> Radix.mapMaybeWithKey (f . Radix.buildBytes))+                 (\_ -> No.mapMaybeWithKey f)++partitionT :: (Eq a, Integral a) => SplitT () a+partitionT = Test splitEq (\_ -> Radix.partition odd) (\_ -> No.partition odd)++partitionWithKeyT :: (Eq a, Integral a) => SplitT () a+partitionWithKeyT =+  let f k a = odd $ sum (fmap fromIntegral k) + a+  in Test splitEq (\_ -> Radix.partitionWithKey (f . Radix.buildBytes))+                  (\_ -> No.partitionWithKey f)++mapEitherT :: (Eq a, Integral a) => SplitT () a+mapEitherT =+  let f a | odd a     = Left a+          | otherwise = Right a++  in Test splitEq (\_ -> Radix.mapEither f) (\_ -> No.mapEither f)++mapEitherWithKeyT :: (Eq a, Integral a) => SplitT () a+mapEitherWithKeyT =+  let f k a | odd (sum (fmap fromIntegral k) + a) = Left a+            | otherwise                = Right a++  in Test splitEq (\_ -> Radix.mapEitherWithKey (f . Radix.buildBytes))+                  (\_ -> No.mapEitherWithKey f)++++mapT :: (Eq a, Num a) => TreeT () a+mapT  = mapT_ Radix.map++mapT_ :: (Eq a, Num a) => (forall x. (x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+mapT_ g =+  let f = (+ 10000)+  in Test treeEq (\_ -> g f) (\_ -> No.map f)++mapWithKeyT :: (Eq a, Num a) => TreeT () a+mapWithKeyT  = mapWithKeyT_ Radix.mapWithKey++mapWithKeyT_+  :: (Eq a, Num a)+  => (forall x. (Radix.Build -> x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+mapWithKeyT_ g =+  let f k = (+ sum (fmap fromIntegral k)) . (+ 10000)+  in Test treeEq (\_ -> g (f . Radix.buildBytes)) (\_ -> No.mapWithKey f)+++foldlT, foldlT' :: (Eq a, Num a) => IdT () a [a]+foldlT  = foldlT_ Radix.foldl+foldlT' = foldlT_ Radix.foldl'++foldlT_ :: Eq a => (forall x. (x -> a -> x) -> x -> RadixTree a -> x) -> IdT () a [a]+foldlT_ g =+  Test (==) (\_ -> g (flip (:)) []) (\_ -> No.foldl (flip (:)) [])++foldlWithKeyT, foldlWithKeyT' :: Eq a => IdT () a [([Word8], a)]+foldlWithKeyT  = foldlWithKeyT_ Radix.foldlWithKey+foldlWithKeyT' = foldlWithKeyT_ Radix.foldlWithKey'++foldlWithKeyT_+  :: Eq a+  => (forall x. (x -> Radix.Build -> a -> x) -> x -> RadixTree a -> x)+  -> IdT () a [([Word8], a)]+foldlWithKeyT_ g =+  Test (==) (\_ -> g (\z k a -> (Radix.buildBytes k, a) : z) [])+            (\_ -> No.foldlWithKey (\z k a -> (k, a) : z) [])++++foldrT, foldrT' :: Eq a => IdT () a [a]+foldrT  = foldrT_ Radix.foldr+foldrT' = foldrT_ Radix.foldr'++foldrT_ :: Eq a => (forall x. (a -> x -> x) -> x -> RadixTree a -> x) -> IdT () a [a]+foldrT_ g = Test (==) (\_ -> g (:) []) (\_ -> No.foldr (:) [])++foldrWithKeyT, foldrWithKeyT' :: (Eq a, Num a) => IdT () a [([Word8], a)]+foldrWithKeyT  = foldrWithKeyT_ Radix.foldrWithKey+foldrWithKeyT' = foldrWithKeyT_ Radix.foldrWithKey'++foldrWithKeyT_+  :: (Eq a, Num a)+  => (forall y. (Radix.Build -> a -> y -> y) -> y -> RadixTree a -> y)+  -> IdT () a [([Word8], a)]+foldrWithKeyT_ g = Test (==) (\_ -> g (\k a -> (:) (Radix.buildBytes k, a)) [])+                             (\_ -> No.foldrWithKey (\k a -> (:) (k, a)) [])++++foldMapT :: Eq a => IdT () a [a]+foldMapT = Test (==) (\_ -> Radix.foldMap (:[])) (\_ -> No.foldMap (:[]))++foldMapWithKeyT :: Eq a => IdT () a [([Word8], a)]+foldMapWithKeyT =+  Test (==) (\_ -> Radix.foldMapWithKey (\k a -> [(Radix.buildBytes k, a)]))+            (\_ -> No.foldMapWithKey (\k a -> [(k, a)]))++++idTreeEq :: Eq a => Identity (RadixTree a) -> Identity (NoTree [Word8] a) -> Bool+idTreeEq (Identity a) (Identity b) = treeEq a b++traverseT+  :: (Eq a, Num a)+  => Test s (RadixTree a) (NoTree [Word8] a)+            (Identity (RadixTree a)) (Identity (NoTree [Word8] a))+traverseT =+  let f = Identity . (+ 10000)+  in Test idTreeEq (\_ -> Radix.traverse f) (\_ -> No.traverse f)++traverseWithKeyT+  :: (Eq a, Num a)+  => Test s (RadixTree a) (NoTree [Word8] a)+            (Identity (RadixTree a)) (Identity (NoTree [Word8] a))+traverseWithKeyT =+  let f k a = Identity $ sum (fmap fromIntegral k) + 10000 + a+  in Test idTreeEq (\_ -> Radix.traverseWithKey (f . Radix.buildBytes))+                   (\_ -> No.traverseWithKey f)++++unionT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+unionT = Test treeEq (Radix.union . fst) (No.unionL . snd)++unionLT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+unionLT = Test treeEq (Radix.unionL . fst) (No.unionL . snd)++unionWithT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+unionWithT = Test treeEq (Radix.unionWith (\_ y -> y) . fst)+                         (No.unionWithKey (\_ _ y -> y) . snd)++unionWithKeyT, mergeUnionT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+unionWithKeyT = unionWithKeyT_ Radix.unionWithKey+mergeUnionT   =+  unionWithKeyT_ $ \f ->+    Radix.merge (\k a b -> Just $! f k a b)+      (\_ -> Just) (\_ -> id) (\_ -> Just) (\_ -> id)++unionWithKeyT_+  :: Eq a+  => ((Radix.Build -> a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a)+  -> TreeT (RadixTree a, NoTree [Word8] a) a+unionWithKeyT_ g =+  let f k a b | odd $ sum (fmap (fromIntegral :: Word8 -> Int) k) = a+              | otherwise                                         = b++  in Test treeEq (g (f . Radix.buildBytes) . fst)+                 (No.unionWithKey f . snd)++++differenceT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+differenceT = Test treeEq (Radix.difference . fst) (No.difference . snd)++differenceWithT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+differenceWithT = Test treeEq (Radix.differenceWith (\_ -> Just) . fst)+                              (No.differenceWithKey (\_ _ -> Just) . snd)++differenceWithKeyT+  , mergeDifferenceT+ :: (Eq a, Integral a) => TreeT (RadixTree a, NoTree [Word8] a) a+differenceWithKeyT = differenceWithKeyT_ Radix.differenceWithKey+mergeDifferenceT    =+  differenceWithKeyT_ $ \f ->+    Radix.merge f (\_ -> Just) (\_ -> id) (\_ _ -> Nothing) (\_ _ -> Radix1.empty)++differenceWithKeyT_+  :: (Eq a, Integral a)+  => ((Radix.Build -> a -> a -> Maybe a) -> RadixTree a -> RadixTree a -> RadixTree a)+  -> TreeT (RadixTree a, NoTree [Word8] a) a+differenceWithKeyT_ g =+  let f k a b | odd $ sum (fmap (fromIntegral :: Word8 -> Int) k) = Just a+              | otherwise                                         = if even b+                                                                      then Just b+                                                                      else Nothing+  in Test treeEq (g (f . Radix.buildBytes) . fst)+                 (No.differenceWithKey f . snd)++++disjointT :: Eq a => IdT (RadixTree a, NoTree [Word8] a) a Bool+disjointT = Test (==) (Radix.disjoint . fst) (\(_, a) -> No.null . No.intersectionL a)++intersectionT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+intersectionT = Test treeEq (Radix.intersection . fst) (No.intersectionL . snd)++intersectionLT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+intersectionLT = Test treeEq (Radix.intersectionL . fst) (No.intersectionL . snd)++intersectionWithT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+intersectionWithT = Test treeEq (Radix.intersectionWith (\_ y -> y) . fst)+                                (No.intersectionWithKey (\_ _ y -> y) . snd)++intersectionWithKeyT, mergeIntersectionT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+intersectionWithKeyT = intersectionWithKeyT_ Radix.intersectionWithKey+mergeIntersectionT   =+  intersectionWithKeyT_ $ \f ->+    Radix.merge (\k a b -> Just $! f k a b)+      (\_ _ -> Nothing) (\_ _ -> Radix1.empty) (\_ _ -> Nothing) (\_ _ -> Radix1.empty)++intersectionWithKeyT_+  :: Eq a+  => ((Radix.Build -> a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a)+  -> TreeT (RadixTree a, NoTree [Word8] a) a+intersectionWithKeyT_ g =+  let f k a b | odd $ sum (fmap (fromIntegral :: Word8 -> Int) k) = a+              | otherwise                                         = b++  in Test treeEq (g (f . Radix.buildBytes) . fst)+                 (No.intersectionWithKey f . snd)++++compareT :: Eq a => IdT (RadixTree a, NoTree [Word8] a) a Radix.PartialOrdering+compareT = Test (==) (Radix.compare (==) . fst) (No.compare . snd)++++test :: Spec+test = do+  describe "Single-key" $ do+    it "lookup"           $ run unary1_ lookupT+    it "find"             $ run unary1  findT+    it "member"           $ run unary1_ memberT+    it "subtree"          $ run unary1_ subtreeT+    it "move/single"      $ run unary1_ moveSingleT+    it "move/thirds"      $ run unary1_ moveThirdsT+    it "insert"           $ run unary1  insertT+    it "insertWith"       $ run unary1  insertWithT+    it "adjust"           $ run unary1  adjustT+    it "delete"           $ run unary1_ deleteT+    it "prune"            $ run unary1R pruneT+    it "update/adjust"    $ run unary1  updateAdjustT+    it "update/delete"    $ run unary1  updateDeleteT+    it "alter/insert"     $ run unary1  alterInsertT+    it "alter/insertWith" $ run unary1  alterInsertWithT+    it "alter/adjust"     $ run unary1  alterAdjustT+    it "alter/delete"     $ run unary1  alterDeleteT+    it "shape/insert"     $ run unary1_ shapeInsertT+    it "shape/adjust"     $ run unary1_ shapeAdjustT+    it "shape/filter"     $ run unary1_ shapeFilterT+    it "shape/delete"     $ run unary1_ shapeDeleteT++  describe "Split" $ do+    it "splitL"           $ run unary1R splitLT+    it "splitLookup"      $ run unary1_ splitLookupT++  describe "Left" $ do+    it "lookupL"               $ run unary1R lookupLT+    it "adjustL"               $ run unary1F adjustLT+    it "adjustLWithKey"        $ run unary1F adjustLWithKeyT+    it "updateL/adjust"        $ run unary1F updateLAdjustT+    it "updateL/delete"        $ run unary1F updateLDeleteT+    it "updateLWithKey/adjust" $ run unary1F updateLWithKeyAdjustT+    it "updateLWithKey/delete" $ run unary1F updateLWithKeyDeleteT+    it "takeL"                 $ run unary1R takeLT++  describe "Right" $ do+    it "lookupR"               $ run unary1R lookupRT+    it "adjustR"               $ run unary1F adjustRT+    it "adjustRWithKey"        $ run unary1F adjustRWithKeyT+    it "updateR/adjust"        $ run unary1F updateRAdjustT+    it "updateR/delete"        $ run unary1F updateRDeleteT+    it "updateRWithKey/adjust" $ run unary1F updateRWithKeyAdjustT+    it "updateRWithKey/delete" $ run unary1F updateRWithKeyDeleteT+    it "takeR"                 $ run unary1R takeRT++  describe "Min" $ do+    it "lookupMin"               $ run unary0 lookupMinT+    it "lookupMinWithKey"        $ run unary0 lookupMinWithKeyT+    it "adjustMin"               $ run unary0 adjustMinT+    it "adjustMinWithKey"        $ run unary0 adjustMinWithKeyT+    it "deleteMin"               $ run unary0 deleteMinT+    it "updateMin/adjust"        $ run unary0 updateMinAdjustT+    it "updateMin/delete"        $ run unary0 updateMinDeleteT+    it "updateMinWithKey/adjust" $ run unary0 updateMinWithKeyAdjustT+    it "updateMinWithKey/delete" $ run unary0 updateMinWithKeyDeleteT+    it "minView"                 $ run unary0 minViewT++  describe "Max" $ do+    it "lookupMax"               $ run unary0 lookupMaxT+    it "lookupMaxWithKey"        $ run unary0 lookupMaxWithKeyT+    it "adjustMax"               $ run unary0 adjustMaxT+    it "adjustMaxWithKey"        $ run unary0 adjustMaxWithKeyT+    it "deleteMax"               $ run unary0 deleteMaxT+    it "updateMax/adjust"        $ run unary0 updateMaxAdjustT+    it "updateMax/delete"        $ run unary0 updateMaxDeleteT+    it "updateMaxWithKey/adjust" $ run unary0 updateMaxWithKeyAdjustT+    it "updateMaxWithKey/delete" $ run unary0 updateMaxWithKeyDeleteT+    it "maxView"                 $ run unary0 maxViewT++  describe "Partition" $ do+    it "filter"           $ run unary0 filterT+    it "filterWithKey"    $ run unary0 filterWithKeyT+    it "mapMaybe"         $ run unary0 mapMaybeT+    it "mapMaybeWithKey"  $ run unary0 mapMaybeWithKeyT+    it "partition"        $ run unary0 partitionT+    it "partitionWithKey" $ run unary0 partitionWithKeyT+    it "mapEither"        $ run unary0 mapEitherT+    it "mapEitherWithKey" $ run unary0 mapEitherWithKeyT++  describe "Full-tree" $ do+    it "prefix"          $ run unary1_ prefixT+    it "map"             $ run unary0  mapT+    it "mapWithKey"      $ run unary0  mapWithKeyT+    it "foldl"           $ run unary0  foldlT+    it "foldl'"          $ run unary0  foldlT'+    it "foldlWithKey"    $ run unary0  foldlWithKeyT+    it "foldlWithKey'"   $ run unary0  foldlWithKeyT'+    it "foldr"           $ run unary0  foldrT+    it "foldr'"          $ run unary0  foldrT'+    it "foldrWithKey"    $ run unary0  foldrWithKeyT+    it "foldrWithKey'"   $ run unary0  foldrWithKeyT'+    it "foldMap"         $ run unary0  foldMapT+    it "foldMapWithKey"  $ run unary0  foldMapWithKeyT+    it "traverse"        $ run unary0  traverseT+    it "traverseWithKey" $ run unary0  traverseWithKeyT++  describe "Merge" $ do+    it "union"                $ run binary  unionT+    it "unionL"               $ run binaryL unionLT+    it "unionWith"            $ run binaryL unionWithT+    it "unionWithKey"         $ run binaryL unionWithKeyT+    it "difference"           $ run binaryL differenceT+    it "differenceWith"       $ run binaryL differenceWithT+    it "differenceWithKey"    $ run binaryL differenceWithKeyT+    it "disjoint/yes"         $ run binary  disjointT+    it "disjoint/no"          $ run binaryL disjointT+    it "intersection"         $ run binary  intersectionT+    it "intersectionL"        $ run binaryL intersectionLT+    it "intersectionWith"     $ run binaryL intersectionWithT+    it "intersectionWithKey"  $ run binaryL intersectionWithKeyT+    it "compare/subset"       $ run subset   compareT+    it "compare/superset"     $ run superset compareT+    it "compare/equal"        $ run equal    compareT+    it "compare/incomparable" $ run binary   compareT+    it "merge/union"          $ run binaryL mergeUnionT+    it "merge/difference"     $ run binaryL mergeDifferenceT+    it "merge/intersection"   $ run binaryL mergeIntersectionT
+ test/properties/Test/RadixTree/Word8/Strict.hs view
@@ -0,0 +1,848 @@+{-# LANGUAGE RankNTypes #-}++module Test.RadixTree.Word8.Strict+  ( test+  ) where++import qualified Data.Radix1Tree.Word8.Strict as Radix1+import           Data.RadixTree.Word8.Strict (RadixTree)+import qualified Data.RadixTree.Word8.Strict as Radix+import           Data.RadixTree.Word8.Strict.Debug+import qualified Data.RadixTree.Word8.Strict.Unsafe as Radix+import           No.Tree (NoTree)+import qualified No.Tree as No+import           Test.Kit+import           Test.RadixNTree.Word8.Sample++import           Data.Functor.Identity+import qualified Data.List as List+import           Data.Word+import           Test.Hspec++++radixFromList :: [([Word8], a)] -> RadixTree a+radixFromList = foldr (\(k, a) p -> Radix.insert (Radix.feedBytes k) a p) Radix.empty++radixToList :: RadixTree a -> [([Word8], a)]+radixToList = Radix.foldrWithKey (\k a -> (:) (Radix.buildBytes k, a)) []++++unary0 :: [Case () (RadixTree Int) (NoTree [Word8] Int)]+unary0 = foldMap (mkUnary0 radixFromList) [zero, one, tip, bin, tiny, small, medium]++unary1F :: [Case (No.Openness, [Word8], Int) (RadixTree Int) (NoTree [Word8] Int)]+unary1F = foldMap (mkUnary1 radixFromList) [zero, one, tip, bin, tiny, small, medium]++unary1R :: [Case (No.Openness, [Word8]) (RadixTree Int) (NoTree [Word8] Int)]+unary1R = augment (\(o, k, _) -> (o, k)) unary1F++unary1 :: [Case ([Word8], Int) (RadixTree Int) (NoTree [Word8] Int)]+unary1 = augment (\(_, k, i) -> (k, i)) unary1F++unary1_ :: [Case [Word8] (RadixTree Int) (NoTree [Word8] Int)]+unary1_ = augment (\(_, k, _) -> k) unary1F++++binary :: [Case (RadixTree Int, NoTree [Word8] Int) (RadixTree Int) (NoTree [Word8] Int)]+binary = foldMap (mkBinary radixFromList) [zero, one, tip, bin, tiny, small, medium]++binaryL :: [Case (RadixTree Int, NoTree [Word8] Int) (RadixTree Int) (NoTree [Word8] Int)]+binaryL = foldMap (mkBinaryL radixFromList) [zero, one, tip, bin, tiny, small, medium]++equal :: [Case (RadixTree Int, NoTree [Word8] Int) (RadixTree Int) (NoTree [Word8] Int)]+equal = foldMap (mkEqual radixFromList) [zero, one, tip, bin, tiny, small, medium]++subset :: [Case (RadixTree Int, NoTree [Word8] Int) (RadixTree Int) (NoTree [Word8] Int)]+subset = foldMap (mkSubset radixFromList) [zero, one, tip, bin, tiny, small, medium]++superset :: [Case (RadixTree Int, NoTree [Word8] Int) (RadixTree Int) (NoTree [Word8] Int)]+superset = foldMap (mkSuperset radixFromList) [zero, one, tip, bin, tiny, small, medium]++++type IdT s a b = Test s (RadixTree a) (NoTree [Word8] a) b b++type TreeT s a = Test s (RadixTree a) (NoTree [Word8] a) (RadixTree a) (NoTree [Word8] a)++treeEq :: Eq a => RadixTree a -> NoTree [Word8] a -> Bool+treeEq pat no =+  case validate pat of+    Valid -> radixToList pat == No.toList no+    _     -> False++type SplitT s a =+       Test s (RadixTree a) (NoTree [Word8] a)+         (Radix.Split a a) (NoTree [Word8] a, NoTree [Word8] a)++splitEq :: Eq a => Radix.Split a a -> (NoTree [Word8] a, NoTree [Word8] a) -> Bool+splitEq (Radix.Split a b) (x, y) = treeEq a x && treeEq b y++type SplitLookupT s a =+       Test s (RadixTree a) (NoTree [Word8] a)+         (Radix.SplitLookup a a a) (NoTree [Word8] a, Maybe a, NoTree [Word8] a)++splitLookupEq+  :: Eq a+  => Radix.SplitLookup a a a -> (NoTree [Word8] a, Maybe a, NoTree [Word8] a) -> Bool+splitLookupEq (Radix.SplitLookup a b c) (x, y, z) = treeEq a x && b == y && treeEq c z++type LookupT s a =+       Test s (RadixTree a) (NoTree [Word8] a)+       (Maybe (Radix.Lookup a)) (Maybe ([Word8], a))++lookupEq :: Eq a => Maybe (Radix.Lookup a) -> Maybe ([Word8], a) -> Bool+lookupEq (Just (Radix.Lookup k a)) (Just (l, b)) = Radix.buildBytes k == l && a == b+lookupEq Nothing                   Nothing       = True+lookupEq _                         _             = False++type MinViewT s a =+       Test s (RadixTree a) (NoTree [Word8] a)+         (Maybe (Radix.ViewL a)) (Maybe ([Word8], a, NoTree [Word8] a))++minViewEq :: Eq a => Maybe (Radix.ViewL a) -> Maybe ([Word8], a, NoTree [Word8] a) -> Bool+minViewEq (Just (Radix.ViewL k a t)) (Just (l, b, no)) =+  Radix.buildBytes k == l && a == b && treeEq t no++minViewEq Nothing                    Nothing           = True+minViewEq _                          _                 = False++type MaxViewT s a =+       Test s (RadixTree a) (NoTree [Word8] a)+         (Maybe (Radix.ViewR a)) (Maybe (NoTree [Word8] a, [Word8], a))++maxViewEq :: Eq a => Maybe (Radix.ViewR a) -> Maybe (NoTree [Word8] a, [Word8], a) -> Bool+maxViewEq (Just (Radix.ViewR t k a)) (Just (no, l, b)) =+  Radix.buildBytes k == l && a == b && treeEq t no++maxViewEq Nothing                    Nothing           = True+maxViewEq _                          _                 = False++++lookupT :: Eq a => IdT [Word8] a (Maybe a)+lookupT = Test (==) (Radix.lookup . Radix.feedBytes) No.lookup++findT :: Eq a => IdT ([Word8], a) a a+findT = Test (==) (\(k, i) -> Radix.find i $ Radix.feedBytes k) (\(k, i) -> No.find i k)++memberT :: Eq a => IdT [Word8] a Bool+memberT = Test (==) (Radix.member . Radix.feedBytes) No.member++subtreeT :: Eq a => TreeT [Word8] a+subtreeT = Test treeEq (Radix.subtree . Radix.feedBytes) No.subtree++moveSingleT :: Eq a => IdT [Word8] a (Maybe a)+moveSingleT =+  Test (==) (\k -> Radix.stop . Radix.move (Radix.feedBytes k) . Radix.cursor)+            No.lookup++moveThirdsT :: Eq a => IdT [Word8] a (Maybe a)+moveThirdsT =+  let thirds xs = let len = length xs+                      ~(as, ys) = List.splitAt (len `quot` 3) xs+                      ~(bs, cs) = List.splitAt (len `quot` 3) ys++                  in Radix.move (Radix.feedBytes cs)+                   . Radix.move (Radix.feedBytes bs)+                   . Radix.move (Radix.feedBytes as)++  in Test (==) (\k -> Radix.stop . thirds k . Radix.cursor) No.lookup++++prefixT :: Eq a => TreeT [Word8] a+prefixT = Test treeEq (Radix.prefix . Radix.feedBytes) No.prefix++insertT :: Eq a => TreeT ([Word8], a) a+insertT = Test treeEq (\(k, i) -> Radix.insert (Radix.feedBytes k) i) (uncurry No.insert)++insertWithT, insertWithT' :: (Eq a, Integral a) => TreeT ([Word8], a) a+insertWithT  = insertWithT_ Radix.insertWith+insertWithT' = insertWithT_ Radix.insertWith'++insertWithT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Radix.Feed -> x -> RadixTree x -> RadixTree x) -> TreeT ([Word8], a) a+insertWithT_ g =+  let f x = (+ fromIntegral x)+  in Test treeEq (\(k, a) -> g (f a) (Radix.feedBytes k) a)+                 (\(k, a) -> No.insertWith (f a) k a)++adjustT, adjustT' :: (Eq a, Integral a) => TreeT ([Word8], a) a+adjustT  = adjustT_ Radix.adjust+adjustT' = adjustT_ Radix.adjust'++adjustT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> Radix.Feed -> RadixTree x -> RadixTree x) -> TreeT ([Word8], a) a+adjustT_ g =+  let f a = (+ fromIntegral a)+  in Test treeEq (\(k, a) -> g (f a) (Radix.feedBytes k))+                 (\(k, a) -> No.adjust (f a) k)++deleteT :: Eq a => TreeT [Word8] a+deleteT = Test treeEq (Radix.delete . Radix.feedBytes) No.delete++pruneT :: Eq a => TreeT (No.Openness, [Word8]) a+pruneT = Test treeEq (\(o, k) -> Radix.prune o $ Radix.feedBytes k) (uncurry No.prune)++updateAdjustT, updateDeleteT :: (Eq a, Integral a) => TreeT ([Word8], a) a+updateAdjustT = updateT_ (\a -> Just . (+ a))+updateDeleteT = updateT_ (\_ _ -> Nothing)++updateT_ :: Eq a => (a -> a -> Maybe a) -> TreeT ([Word8], a) a+updateT_ f = Test treeEq (\(k, a) -> Radix.update (f a) (Radix.feedBytes k))+                         (\(k, a) -> No.update (f a) k)++alterInsertT+  , alterInsertWithT+  , alterAdjustT+  , alterDeleteT+ :: (Eq a, Integral a) => TreeT ([Word8], a) a+alterInsertT     = alterT_ (\a _ -> Just a)+alterInsertWithT = alterT_ (\a -> Just . maybe a (+ a))+alterAdjustT     = alterT_ (\a -> fmap (+ a))+alterDeleteT     = alterT_ (\_ _ -> Nothing)++alterT_ :: Eq a => (a -> Maybe a -> Maybe a) -> TreeT ([Word8], a) a+alterT_ f = Test treeEq (\(k, a) -> Radix.alter (f a) (Radix.feedBytes k))+                        (\(k, a) -> No.alter (f a) k)++shapeInsertT :: (Eq a, Integral a) => TreeT [Word8] a+shapeInsertT =+  Test treeEq+    (Radix.shape (Radix.insert (Radix.feedBytes [1, 2, 3]) 10000) . Radix.feedBytes)+    (No.shape (No.insert [1, 2, 3] 10000))++shapeAdjustT :: (Eq a, Integral a) => TreeT [Word8] a+shapeAdjustT = Test treeEq (Radix.shape (Radix.map negate) . Radix.feedBytes)+                           (No.shape (No.map negate))++shapeFilterT :: (Eq a, Integral a) => TreeT [Word8] a+shapeFilterT = Test treeEq (Radix.shape (Radix.filter odd) . Radix.feedBytes)+                           (No.shape (No.filter odd))++shapeDeleteT :: (Eq a, Integral a) => TreeT [Word8] a+shapeDeleteT = Test treeEq (Radix.shape (\_ -> Radix.empty) . Radix.feedBytes)+                           (No.shape (\_ -> No.empty))++++splitLT :: Eq a => SplitT (No.Openness, [Word8]) a+splitLT = Test splitEq (\(o, k) -> Radix.splitL o $ Radix.feedBytes k) (uncurry No.splitL)++splitLookupT :: Eq a => SplitLookupT [Word8] a+splitLookupT = Test splitLookupEq (Radix.splitLookup . Radix.feedBytes) No.splitLookup++++lookupLT :: Eq a => LookupT (No.Openness, [Word8]) a+lookupLT = Test lookupEq (\(o, k) -> Radix.lookupL o $ Radix.feedBytes k)+                         (uncurry No.lookupL)++adjustLT, adjustLT' :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+adjustLT  = adjustLT_ Radix.adjustL+adjustLT' = adjustLT_ Radix.adjustL'++adjustLT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> No.Openness -> Radix.Feed -> RadixTree x -> RadixTree x)+  -> TreeT (No.Openness, [Word8], a) a+adjustLT_ g =+  let f a = (+ a)+  in Test treeEq (\(o, k, a) -> g (f a) o $ Radix.feedBytes k)+                 (\(o, k, a) -> No.adjustL (f a) o k)++adjustLWithKeyT+  , adjustLWithKeyT'+ :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+adjustLWithKeyT  = adjustLWithKeyT_ Radix.adjustLWithKey+adjustLWithKeyT' = adjustLWithKeyT_ Radix.adjustLWithKey'++adjustLWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Radix.Build -> x -> x) -> No.Openness -> Radix.Feed -> RadixTree x -> RadixTree x)+  -> TreeT (No.Openness, [Word8], a) a+adjustLWithKeyT_ g =+  let f a k = (+ sum (fmap fromIntegral k)) . (+ a)+  in Test treeEq (\(o, k, a) -> g (f a . Radix.buildBytes) o $ Radix.feedBytes k)+                 (\(o, k, a) -> No.adjustLWithKey (f a) o k)++updateLAdjustT+  , updateLDeleteT+ :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+updateLAdjustT = updateLT_ (\a -> Just . (+ a))+updateLDeleteT = updateLT_ (\_ _ -> Nothing)++updateLT_+  :: (Eq a, Integral a)+  => (a -> a -> Maybe a) -> TreeT (No.Openness, [Word8], a) a+updateLT_ f =+  Test treeEq (\(o, k, a) -> Radix.updateL (f a) o $ Radix.feedBytes k)+              (\(o, k, a) -> No.updateL (f a) o k)++updateLWithKeyAdjustT+  , updateLWithKeyDeleteT+ :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+updateLWithKeyAdjustT = updateLWithKeyT_ (\a k -> Just . (+ sum (fmap fromIntegral k)) . (+ a))+updateLWithKeyDeleteT = updateLWithKeyT_ (\_ _ _ -> Nothing)++updateLWithKeyT_+  :: (Eq a, Integral a)+  => (a -> [Word8] -> a -> Maybe a) -> TreeT (No.Openness, [Word8], a) a+updateLWithKeyT_ f =+  Test treeEq (\(o, k, a) -> Radix.updateLWithKey (f a . Radix.buildBytes) o $ Radix.feedBytes k)+              (\(o, k, a) -> No.updateLWithKey (f a) o k)++takeLT :: Eq a => TreeT (No.Openness, [Word8]) a+takeLT = Test treeEq (\(o, k) -> Radix.takeL o $ Radix.feedBytes k)+                     (uncurry No.takeL)++++lookupRT :: Eq a => LookupT (No.Openness, [Word8]) a+lookupRT = Test lookupEq (\(o, k) -> Radix.lookupR o $ Radix.feedBytes k)+                         (uncurry No.lookupR)++adjustRT, adjustRT' :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+adjustRT  = adjustRT_ Radix.adjustR+adjustRT' = adjustRT_ Radix.adjustR'++adjustRT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> No.Openness -> Radix.Feed -> RadixTree x -> RadixTree x)+  -> TreeT (No.Openness, [Word8], a) a+adjustRT_ g =+  let f a = (+ a)+  in Test treeEq (\(o, k, a) -> g (f a) o $ Radix.feedBytes k)+                 (\(o, k, a) -> No.adjustR (f a) o k)++adjustRWithKeyT+  , adjustRWithKeyT'+ :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+adjustRWithKeyT  = adjustRWithKeyT_ Radix.adjustRWithKey+adjustRWithKeyT' = adjustRWithKeyT_ Radix.adjustRWithKey'++adjustRWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Radix.Build -> x -> x) -> No.Openness -> Radix.Feed -> RadixTree x -> RadixTree x)+  -> TreeT (No.Openness, [Word8], a) a+adjustRWithKeyT_ g =+  let f a k = (+ sum (fmap fromIntegral k)) . (+ a)+  in Test treeEq (\(o, k, a) -> g (f a . Radix.buildBytes) o $ Radix.feedBytes k)+                 (\(o, k, a) -> No.adjustRWithKey (f a) o k)++updateRAdjustT+  , updateRDeleteT+ :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+updateRAdjustT = updateRT_ (\a -> Just . (+ a))+updateRDeleteT = updateRT_ (\_ _ -> Nothing)++updateRT_+  :: (Eq a, Integral a)+  => (a -> a -> Maybe a) -> TreeT (No.Openness, [Word8], a) a+updateRT_ f =+  Test treeEq (\(o, k, a) -> Radix.updateR (f a) o $ Radix.feedBytes k)+              (\(o, k, a) -> No.updateR (f a) o k)++updateRWithKeyAdjustT+  , updateRWithKeyDeleteT+ :: (Eq a, Integral a) => TreeT (No.Openness, [Word8], a) a+updateRWithKeyAdjustT = updateRWithKeyT_ (\a k -> Just . (+ sum (fmap fromIntegral k)) . (+ a))+updateRWithKeyDeleteT = updateRWithKeyT_ (\_ _ _ -> Nothing)++updateRWithKeyT_+  :: (Eq a, Integral a)+  => (a -> [Word8] -> a -> Maybe a) -> TreeT (No.Openness, [Word8], a) a+updateRWithKeyT_ f =+  Test treeEq (\(o, k, a) -> Radix.updateRWithKey (f a . Radix.buildBytes) o $ Radix.feedBytes k)+              (\(o, k, a) -> No.updateRWithKey (f a) o k)++takeRT :: Eq a => TreeT (No.Openness, [Word8]) a+takeRT = Test treeEq (\(o, k) -> Radix.takeR o $ Radix.feedBytes k)+                     (uncurry No.takeR)++++lookupMinT :: Eq a => IdT () a (Maybe a)+lookupMinT = Test (==) (\_ -> Radix.lookupMin) (\_ -> No.lookupMin)++lookupMinWithKeyT :: Eq a => LookupT () a+lookupMinWithKeyT =+  Test lookupEq (\_ -> Radix.lookupMinWithKey) (\_ -> No.lookupMinWithKey)++adjustMinT, adjustMinT' :: (Eq a, Integral a) => TreeT () a+adjustMinT  = adjustMinT_ Radix.adjustMin+adjustMinT' = adjustMinT_ Radix.adjustMin'++adjustMinT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+adjustMinT_ f = Test treeEq (\_ -> f (+ 10000)) (\_ -> No.adjustMin (+ 10000))++adjustMinWithKeyT, adjustMinWithKeyT' :: (Eq a, Integral a) => TreeT () a+adjustMinWithKeyT  = adjustMinWithKeyT_ Radix.adjustMinWithKey+adjustMinWithKeyT' = adjustMinWithKeyT_ Radix.adjustMinWithKey'++adjustMinWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Radix.Build -> x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+adjustMinWithKeyT_ g =+  let f k = (+ sum (fmap fromIntegral k))+  in Test treeEq (\_ -> g (f . Radix.buildBytes)) (\_ -> No.adjustMinWithKey f)++deleteMinT :: (Eq a, Integral a) => TreeT () a+deleteMinT = Test treeEq (\_ -> Radix.deleteMin) (\_ -> No.deleteMin)++updateMinAdjustT, updateMinDeleteT :: (Eq a, Integral a) => TreeT () a+updateMinAdjustT = updateMinT_ (Just . (+ 10000))+updateMinDeleteT = updateMinT_ (\_ -> Nothing)++updateMinT_ :: (Eq a, Integral a) => (a -> Maybe a) -> TreeT () a+updateMinT_ f = Test treeEq (\_ -> Radix.updateMin f) (\_ -> No.updateMin f)++updateMinWithKeyAdjustT, updateMinWithKeyDeleteT :: (Eq a, Integral a) => TreeT () a+updateMinWithKeyAdjustT = updateMinWithKeyT_ (\k -> Just . (+ sum (fmap fromIntegral k)))+updateMinWithKeyDeleteT = updateMinWithKeyT_ (\_ _ -> Nothing)++updateMinWithKeyT_ :: (Eq a, Integral a) => ([Word8] -> a -> Maybe a) -> TreeT () a+updateMinWithKeyT_ f =+  Test treeEq (\_ -> Radix.updateMinWithKey (f . Radix.buildBytes))+              (\_ -> No.updateMinWithKey f)++minViewT :: Eq a => MinViewT () a+minViewT = Test minViewEq (\_ -> Radix.minView) (\_ -> No.minView)++++lookupMaxT :: Eq a => IdT () a (Maybe a)+lookupMaxT = Test (==) (\_ -> Radix.lookupMax) (\_ -> No.lookupMax)++lookupMaxWithKeyT :: Eq a => LookupT () a+lookupMaxWithKeyT =+  Test lookupEq (\_ -> Radix.lookupMaxWithKey) (\_ -> No.lookupMaxWithKey)++adjustMaxT, adjustMaxT' :: (Eq a, Integral a) => TreeT () a+adjustMaxT  = adjustMaxT_ Radix.adjustMax+adjustMaxT' = adjustMaxT_ Radix.adjustMax'++adjustMaxT_+  :: (Eq a, Integral a)+  => (forall x. (x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+adjustMaxT_ f = Test treeEq (\_ -> f (+ 10000)) (\_ -> No.adjustMax (+ 10000))++adjustMaxWithKeyT, adjustMaxWithKeyT' :: (Eq a, Integral a) => TreeT () a+adjustMaxWithKeyT  = adjustMaxWithKeyT_ Radix.adjustMaxWithKey+adjustMaxWithKeyT' = adjustMaxWithKeyT_ Radix.adjustMaxWithKey'++adjustMaxWithKeyT_+  :: (Eq a, Integral a)+  => (forall x. (Radix.Build -> x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+adjustMaxWithKeyT_ g =+  let f k = (+ sum (fmap fromIntegral k))+  in Test treeEq (\_ -> g (f . Radix.buildBytes)) (\_ -> No.adjustMaxWithKey f)++deleteMaxT :: (Eq a, Integral a) => TreeT () a+deleteMaxT = Test treeEq (\_ -> Radix.deleteMax) (\_ -> No.deleteMax)++updateMaxAdjustT, updateMaxDeleteT :: (Eq a, Integral a) => TreeT () a+updateMaxAdjustT = updateMaxT_ (Just . (+ 10000))+updateMaxDeleteT = updateMaxT_ (\_ -> Nothing)++updateMaxT_ :: (Eq a, Integral a) => (a -> Maybe a) -> TreeT () a+updateMaxT_ f = Test treeEq (\_ -> Radix.updateMax f) (\_ -> No.updateMax f)++updateMaxWithKeyAdjustT, updateMaxWithKeyDeleteT :: (Eq a, Integral a) => TreeT () a+updateMaxWithKeyAdjustT = updateMaxWithKeyT_ (\k -> Just . (+ sum (fmap fromIntegral k)))+updateMaxWithKeyDeleteT = updateMaxWithKeyT_ (\_ _ -> Nothing)++updateMaxWithKeyT_ :: (Eq a, Integral a) => ([Word8] -> a -> Maybe a) -> TreeT () a+updateMaxWithKeyT_ f =+  Test treeEq (\_ -> Radix.updateMaxWithKey (f . Radix.buildBytes))+              (\_ -> No.updateMaxWithKey f)++maxViewT :: Eq a => MaxViewT () a+maxViewT = Test maxViewEq (\_ -> Radix.maxView) (\_ -> No.maxView)++++filterT :: (Eq a, Integral a) => TreeT () a+filterT = Test treeEq (\_ -> Radix.filter odd) (\_ -> No.filter odd)++filterWithKeyT :: (Eq a, Integral a) => TreeT () a+filterWithKeyT =+  let f k a = odd $ sum (fmap fromIntegral k) + a+  in Test treeEq (\_ -> Radix.filterWithKey (f . Radix.buildBytes))+                 (\_ -> No.filterWithKey f)++mapMaybeT :: (Eq a, Integral a) => TreeT () a+mapMaybeT =+  let f a | odd a     = Nothing+          | otherwise = Just a++  in Test treeEq (\_ -> Radix.mapMaybe f) (\_ -> No.mapMaybe f)++mapMaybeWithKeyT :: (Eq a, Integral a) => TreeT () a+mapMaybeWithKeyT =+  let f k a | odd (sum (fmap fromIntegral k) + a) = Nothing+            | otherwise                           = Just a++  in Test treeEq (\_ -> Radix.mapMaybeWithKey (f . Radix.buildBytes))+                 (\_ -> No.mapMaybeWithKey f)++partitionT :: (Eq a, Integral a) => SplitT () a+partitionT = Test splitEq (\_ -> Radix.partition odd) (\_ -> No.partition odd)++partitionWithKeyT :: (Eq a, Integral a) => SplitT () a+partitionWithKeyT =+  let f k a = odd $ sum (fmap fromIntegral k) + a+  in Test splitEq (\_ -> Radix.partitionWithKey (f . Radix.buildBytes))+                  (\_ -> No.partitionWithKey f)++mapEitherT :: (Eq a, Integral a) => SplitT () a+mapEitherT =+  let f a | odd a     = Left a+          | otherwise = Right a++  in Test splitEq (\_ -> Radix.mapEither f) (\_ -> No.mapEither f)++mapEitherWithKeyT :: (Eq a, Integral a) => SplitT () a+mapEitherWithKeyT =+  let f k a | odd (sum (fmap fromIntegral k) + a) = Left a+            | otherwise                = Right a++  in Test splitEq (\_ -> Radix.mapEitherWithKey (f . Radix.buildBytes))+                  (\_ -> No.mapEitherWithKey f)++++mapT, mapT' :: (Eq a, Num a) => TreeT () a+mapT  = mapT_ Radix.map+mapT' = mapT_ Radix.map'++mapT_ :: (Eq a, Num a) => (forall x. (x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+mapT_ g =+  let f = (+ 10000)+  in Test treeEq (\_ -> g f) (\_ -> No.map f)++mapWithKeyT, mapWithKeyT' :: (Eq a, Num a) => TreeT () a+mapWithKeyT  = mapWithKeyT_ Radix.mapWithKey+mapWithKeyT' = mapWithKeyT_ Radix.mapWithKey'++mapWithKeyT_+  :: (Eq a, Num a)+  => (forall x. (Radix.Build -> x -> x) -> RadixTree x -> RadixTree x) -> TreeT () a+mapWithKeyT_ g =+  let f k = (+ sum (fmap fromIntegral k)) . (+ 10000)+  in Test treeEq (\_ -> g (f . Radix.buildBytes)) (\_ -> No.mapWithKey f)+++foldlT, foldlT' :: (Eq a, Num a) => IdT () a [a]+foldlT  = foldlT_ Radix.foldl+foldlT' = foldlT_ Radix.foldl'++foldlT_ :: Eq a => (forall x. (x -> a -> x) -> x -> RadixTree a -> x) -> IdT () a [a]+foldlT_ g =+  Test (==) (\_ -> g (flip (:)) []) (\_ -> No.foldl (flip (:)) [])++foldlWithKeyT, foldlWithKeyT' :: Eq a => IdT () a [([Word8], a)]+foldlWithKeyT  = foldlWithKeyT_ Radix.foldlWithKey+foldlWithKeyT' = foldlWithKeyT_ Radix.foldlWithKey'++foldlWithKeyT_+  :: Eq a+  => (forall x. (x -> Radix.Build -> a -> x) -> x -> RadixTree a -> x)+  -> IdT () a [([Word8], a)]+foldlWithKeyT_ g =+  Test (==) (\_ -> g (\z k a -> (Radix.buildBytes k, a) : z) [])+            (\_ -> No.foldlWithKey (\z k a -> (k, a) : z) [])++++foldrT, foldrT' :: Eq a => IdT () a [a]+foldrT  = foldrT_ Radix.foldr+foldrT' = foldrT_ Radix.foldr'++foldrT_ :: Eq a => (forall x. (a -> x -> x) -> x -> RadixTree a -> x) -> IdT () a [a]+foldrT_ g = Test (==) (\_ -> g (:) []) (\_ -> No.foldr (:) [])++foldrWithKeyT, foldrWithKeyT' :: (Eq a, Num a) => IdT () a [([Word8], a)]+foldrWithKeyT  = foldrWithKeyT_ Radix.foldrWithKey+foldrWithKeyT' = foldrWithKeyT_ Radix.foldrWithKey'++foldrWithKeyT_+  :: (Eq a, Num a)+  => (forall y. (Radix.Build -> a -> y -> y) -> y -> RadixTree a -> y)+  -> IdT () a [([Word8], a)]+foldrWithKeyT_ g = Test (==) (\_ -> g (\k a -> (:) (Radix.buildBytes k, a)) [])+                             (\_ -> No.foldrWithKey (\k a -> (:) (k, a)) [])++++foldMapT :: Eq a => IdT () a [a]+foldMapT = Test (==) (\_ -> Radix.foldMap (:[])) (\_ -> No.foldMap (:[]))++foldMapWithKeyT :: Eq a => IdT () a [([Word8], a)]+foldMapWithKeyT =+  Test (==) (\_ -> Radix.foldMapWithKey (\k a -> [(Radix.buildBytes k, a)]))+            (\_ -> No.foldMapWithKey (\k a -> [(k, a)]))++++idTreeEq :: Eq a => Identity (RadixTree a) -> Identity (NoTree [Word8] a) -> Bool+idTreeEq (Identity a) (Identity b) = treeEq a b++traverseT+  :: (Eq a, Num a)+  => Test s (RadixTree a) (NoTree [Word8] a)+            (Identity (RadixTree a)) (Identity (NoTree [Word8] a))+traverseT =+  let f = Identity . (+ 10000)+  in Test idTreeEq (\_ -> Radix.traverse f) (\_ -> No.traverse f)++traverseWithKeyT+  :: (Eq a, Num a)+  => Test s (RadixTree a) (NoTree [Word8] a)+            (Identity (RadixTree a)) (Identity (NoTree [Word8] a))+traverseWithKeyT =+  let f k a = Identity $ sum (fmap fromIntegral k) + 10000 + a+  in Test idTreeEq (\_ -> Radix.traverseWithKey (f . Radix.buildBytes))+                   (\_ -> No.traverseWithKey f)++++unionT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+unionT = Test treeEq (Radix.union . fst) (No.unionL . snd)++unionLT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+unionLT = Test treeEq (Radix.unionL . fst) (No.unionL . snd)++unionWithT' :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+unionWithT' = Test treeEq (Radix.unionWith' (\_ y -> y) . fst)+                          (No.unionWithKey (\_ _ y -> y) . snd)++unionWithKeyT', mergeUnionT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+unionWithKeyT' = unionWithKeyT_ Radix.unionWithKey'+mergeUnionT    =+  unionWithKeyT_ $ \f ->+    Radix.merge (\k a b -> Just $! f k a b)+      (\_ -> Just) (\_ -> id) (\_ -> Just) (\_ -> id)++unionWithKeyT_+  :: Eq a+  => ((Radix.Build -> a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a)+  -> TreeT (RadixTree a, NoTree [Word8] a) a+unionWithKeyT_ g =+  let f k a b | odd $ sum (fmap (fromIntegral :: Word8 -> Int) k) = a+              | otherwise                                         = b++  in Test treeEq (g (f . Radix.buildBytes) . fst)+                 (No.unionWithKey f . snd)++++differenceT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+differenceT = Test treeEq (Radix.difference . fst) (No.difference . snd)++differenceWithT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+differenceWithT = Test treeEq (Radix.differenceWith (\_ -> Just) . fst)+                              (No.differenceWithKey (\_ _ -> Just) . snd)++differenceWithKeyT+  , mergeDifferenceT+ :: (Eq a, Integral a) => TreeT (RadixTree a, NoTree [Word8] a) a+differenceWithKeyT = differenceWithKeyT_ Radix.differenceWithKey+mergeDifferenceT    =+  differenceWithKeyT_ $ \f ->+    Radix.merge f (\_ -> Just) (\_ -> id) (\_ _ -> Nothing) (\_ _ -> Radix1.empty)++differenceWithKeyT_+  :: (Eq a, Integral a)+  => ((Radix.Build -> a -> a -> Maybe a) -> RadixTree a -> RadixTree a -> RadixTree a)+  -> TreeT (RadixTree a, NoTree [Word8] a) a+differenceWithKeyT_ g =+  let f k a b | odd $ sum (fmap (fromIntegral :: Word8 -> Int) k) = Just a+              | otherwise                                         = if even b+                                                                      then Just b+                                                                      else Nothing+  in Test treeEq (g (f . Radix.buildBytes) . fst)+                 (No.differenceWithKey f . snd)++++disjointT :: Eq a => IdT (RadixTree a, NoTree [Word8] a) a Bool+disjointT = Test (==) (Radix.disjoint . fst) (\(_, a) -> No.null . No.intersectionL a)++intersectionT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+intersectionT = Test treeEq (Radix.intersection . fst) (No.intersectionL . snd)++intersectionLT :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+intersectionLT = Test treeEq (Radix.intersectionL . fst) (No.intersectionL . snd)++intersectionWithT' :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+intersectionWithT' = Test treeEq (Radix.intersectionWith' (\_ y -> y) . fst)+                                 (No.intersectionWithKey (\_ _ y -> y) . snd)++intersectionWithKeyT'+  , mergeIntersectionT+ :: Eq a => TreeT (RadixTree a, NoTree [Word8] a) a+intersectionWithKeyT' = intersectionWithKeyT_ Radix.intersectionWithKey'+mergeIntersectionT    =+  intersectionWithKeyT_ $ \f ->+    Radix.merge (\k a b -> Just $! f k a b)+      (\_ _ -> Nothing) (\_ _ -> Radix1.empty) (\_ _ -> Nothing) (\_ _ -> Radix1.empty)++intersectionWithKeyT_+  :: Eq a+  => ((Radix.Build -> a -> a -> a) -> RadixTree a -> RadixTree a -> RadixTree a)+  -> TreeT (RadixTree a, NoTree [Word8] a) a+intersectionWithKeyT_ g =+  let f k a b | odd $ sum (fmap (fromIntegral :: Word8 -> Int) k) = a+              | otherwise                                         = b++  in Test treeEq (g (f . Radix.buildBytes) . fst)+                 (No.intersectionWithKey f . snd)++++compareT :: Eq a => IdT (RadixTree a, NoTree [Word8] a) a Radix.PartialOrdering+compareT = Test (==) (Radix.compare (==) . fst) (No.compare . snd)++++test :: Spec+test = do+  describe "Single-key" $ do+    it "lookup"           $ run unary1_ lookupT+    it "find"             $ run unary1  findT+    it "member"           $ run unary1_ memberT+    it "subtree"          $ run unary1_ subtreeT+    it "move/single"      $ run unary1_ moveSingleT+    it "move/thirds"      $ run unary1_ moveThirdsT+    it "insert"           $ run unary1  insertT+    it "insertWith"       $ run unary1  insertWithT+    it "insertWith'"      $ run unary1  insertWithT'+    it "adjust"           $ run unary1  adjustT+    it "adjust'"          $ run unary1  adjustT'+    it "delete"           $ run unary1_ deleteT+    it "prune"            $ run unary1R pruneT+    it "update/adjust"    $ run unary1  updateAdjustT+    it "update/delete"    $ run unary1  updateDeleteT+    it "alter/insert"     $ run unary1  alterInsertT+    it "alter/insertWith" $ run unary1  alterInsertWithT+    it "alter/adjust"     $ run unary1  alterAdjustT+    it "alter/delete"     $ run unary1  alterDeleteT+    it "shape/insert"     $ run unary1_ shapeInsertT+    it "shape/adjust"     $ run unary1_ shapeAdjustT+    it "shape/filter"     $ run unary1_ shapeFilterT+    it "shape/delete"     $ run unary1_ shapeDeleteT++  describe "Split" $ do+    it "splitL"           $ run unary1R splitLT+    it "splitLookup"      $ run unary1_ splitLookupT++  describe "Left" $ do+    it "lookupL"               $ run unary1R lookupLT+    it "adjustL"               $ run unary1F adjustLT+    it "adjustL'"              $ run unary1F adjustLT'+    it "adjustLWithKey"        $ run unary1F adjustLWithKeyT+    it "adjustLWithKey'"       $ run unary1F adjustLWithKeyT'+    it "updateL/adjust"        $ run unary1F updateLAdjustT+    it "updateL/delete"        $ run unary1F updateLDeleteT+    it "updateLWithKey/adjust" $ run unary1F updateLWithKeyAdjustT+    it "updateLWithKey/delete" $ run unary1F updateLWithKeyDeleteT+    it "takeL"                 $ run unary1R takeLT++  describe "Right" $ do+    it "lookupR"               $ run unary1R lookupRT+    it "adjustR"               $ run unary1F adjustRT+    it "adjustR'"              $ run unary1F adjustRT'+    it "adjustRWithKey"        $ run unary1F adjustRWithKeyT+    it "adjustRWithKey'"       $ run unary1F adjustRWithKeyT'+    it "updateR/adjust"        $ run unary1F updateRAdjustT+    it "updateR/delete"        $ run unary1F updateRDeleteT+    it "updateRWithKey/adjust" $ run unary1F updateRWithKeyAdjustT+    it "updateRWithKey/delete" $ run unary1F updateRWithKeyDeleteT+    it "takeR"                 $ run unary1R takeRT++  describe "Min" $ do+    it "lookupMin"               $ run unary0 lookupMinT+    it "lookupMinWithKey"        $ run unary0 lookupMinWithKeyT+    it "adjustMin"               $ run unary0 adjustMinT+    it "adjustMinWithKey"        $ run unary0 adjustMinWithKeyT+    it "adjustMin'"              $ run unary0 adjustMinT'+    it "adjustMinWithKey'"       $ run unary0 adjustMinWithKeyT'+    it "deleteMin"               $ run unary0 deleteMinT+    it "updateMin/adjust"        $ run unary0 updateMinAdjustT+    it "updateMin/delete"        $ run unary0 updateMinDeleteT+    it "updateMinWithKey/adjust" $ run unary0 updateMinWithKeyAdjustT+    it "updateMinWithKey/delete" $ run unary0 updateMinWithKeyDeleteT+    it "minView"                 $ run unary0 minViewT++  describe "Max" $ do+    it "lookupMax"               $ run unary0 lookupMaxT+    it "lookupMaxWithKey"        $ run unary0 lookupMaxWithKeyT+    it "adjustMax"               $ run unary0 adjustMaxT+    it "adjustMaxWithKey"        $ run unary0 adjustMaxWithKeyT+    it "adjustMax'"              $ run unary0 adjustMaxT'+    it "adjustMaxWithKey'"       $ run unary0 adjustMaxWithKeyT'+    it "deleteMax"               $ run unary0 deleteMaxT+    it "updateMax/adjust"        $ run unary0 updateMaxAdjustT+    it "updateMax/delete"        $ run unary0 updateMaxDeleteT+    it "updateMaxWithKey/adjust" $ run unary0 updateMaxWithKeyAdjustT+    it "updateMaxWithKey/delete" $ run unary0 updateMaxWithKeyDeleteT+    it "maxView"                 $ run unary0 maxViewT++  describe "Partition" $ do+    it "filter"           $ run unary0 filterT+    it "filterWithKey"    $ run unary0 filterWithKeyT+    it "mapMaybe"         $ run unary0 mapMaybeT+    it "mapMaybeWithKey"  $ run unary0 mapMaybeWithKeyT+    it "partition"        $ run unary0 partitionT+    it "partitionWithKey" $ run unary0 partitionWithKeyT+    it "mapEither"        $ run unary0 mapEitherT+    it "mapEitherWithKey" $ run unary0 mapEitherWithKeyT++  describe "Full-tree" $ do+    it "prefix"          $ run unary1_ prefixT+    it "map"             $ run unary0  mapT+    it "map'"            $ run unary0  mapT'+    it "mapWithKey"      $ run unary0  mapWithKeyT+    it "mapWithKey'"     $ run unary0  mapWithKeyT'+    it "foldl"           $ run unary0  foldlT+    it "foldl'"          $ run unary0  foldlT'+    it "foldlWithKey"    $ run unary0  foldlWithKeyT+    it "foldlWithKey'"   $ run unary0  foldlWithKeyT'+    it "foldr"           $ run unary0  foldrT+    it "foldr'"          $ run unary0  foldrT'+    it "foldrWithKey"    $ run unary0  foldrWithKeyT+    it "foldrWithKey'"   $ run unary0  foldrWithKeyT'+    it "foldMap"         $ run unary0  foldMapT+    it "foldMapWithKey"  $ run unary0  foldMapWithKeyT+    it "traverse"        $ run unary0  traverseT+    it "traverseWithKey" $ run unary0  traverseWithKeyT++  describe "Merge" $ do+    it "union"                $ run binary  unionT+    it "unionL"               $ run binaryL unionLT+    it "unionWith'"           $ run binaryL unionWithT'+    it "unionWithKey'"        $ run binaryL unionWithKeyT'+    it "difference"           $ run binaryL differenceT+    it "differenceWith"       $ run binaryL differenceWithT+    it "differenceWithKey"    $ run binaryL differenceWithKeyT+    it "disjoint/yes"         $ run binary  disjointT+    it "disjoint/no"          $ run binaryL disjointT+    it "intersection"         $ run binary  intersectionT+    it "intersectionL"        $ run binaryL intersectionLT+    it "intersectionWith'"    $ run binaryL intersectionWithT'+    it "intersectionWithKey'" $ run binaryL intersectionWithKeyT'+    it "compare/subset"       $ run subset   compareT+    it "compare/superset"     $ run superset compareT+    it "compare/equal"        $ run equal    compareT+    it "compare/incomparable" $ run binary   compareT+    it "merge/union"          $ run binaryL mergeUnionT+    it "merge/difference"     $ run binaryL mergeDifferenceT+    it "merge/intersection"   $ run binaryL mergeIntersectionT
+ test/properties/Test/Random.hs view
@@ -0,0 +1,42 @@+module Test.Random+  ( list+  , list1+  , shuffle+  ) where++import           Data.List+import           Data.List.NonEmpty (NonEmpty (..))+import           System.Random++++list :: (g -> (a, g)) -> Int -> g -> ([a], g)+list gen = go+  where+    go n g+      | n <= 0    = ([], g)+      | otherwise = let ~(a, g')   = gen g+                        ~(as, g'') = go (n - 1) g'+                    in (a:as, g'')++list1 :: (g -> (a, g)) -> Int -> g -> (NonEmpty a, g)+list1 gen n g =+  let ~(a, g') = gen g+  in if n <= 1+       then (a :| [], g')+       else let ~(as, g'') = list gen (n - 1) g'+            in (a :| as, g'')++++shuffle :: RandomGen g => [a] -> g -> ([a], g)+shuffle as g = let ~(bs, g') = ziplist as g+               in (fmap snd $ sortBy (\a b -> fst a `compare` fst b) bs, g')+  where+    ziplist :: RandomGen g => [a] -> g -> ([(Int, a)], g)+    ziplist xs h =+      case xs of+        []   -> ([], h)+        x:ys -> let ~(n, h')   = uniform h+                    ~(zs, h'') = ziplist ys h'+                in ((n, x):zs, h'')
+ test/properties/Test/Zebra/Word.hs view
@@ -0,0 +1,344 @@+{-# LANGUAGE RankNTypes #-}++module Test.Zebra.Word+  ( test+  ) where++import           Data.Zebra.Word (Zebra, Color (..), Range (..))+import qualified Data.Zebra.Word as Zebra+import           Data.Zebra.Word.Debug+import           No.Set.Word (NoSet)+import qualified No.Set.Word as No+import           Test.Kit+import           Test.Zebra.Word.Sample++import           Numeric.Natural+import           Test.Hspec++++setFromList :: Color -> ((Word -> Color -> Zebra -> Zebra) -> Zebra -> a) -> a+setFromList c f = f Zebra.fillL (Zebra.Mono c)++setToList :: Zebra -> [(Color, Word, Word)]+setToList = Zebra.foldr (\(Range kL kR) c -> (:) (c, kL, kR)) []++noToList :: NoSet -> [(Color, Word, Word)]+noToList = No.foldr (\(Range kL kR) c -> (:) (c, kL, kR)) []++++unary0 :: [Case () Zebra NoSet]+unary0 = foldMap (mkUnary0 setFromList) [zero, one, tiny, small, medium] --, large]++++unary1 :: [Case (Word, Color) Zebra NoSet]+unary1 = foldMap (mkUnary1 setFromList) [zero, one, tiny, small, medium] --, large]++unary1_ :: [Case Word Zebra NoSet]+unary1_ = augment fst unary1+++unary2 :: [Case (Range, Color) Zebra NoSet]+unary2 = foldMap (mkUnary2 setFromList) [zero, one, tiny, small, medium] --, large]++unary2_ :: [Case Range Zebra NoSet]+unary2_ = augment fst unary2++++binaryL, equal :: [Case (Zebra, NoSet) Zebra NoSet]+binaryL  = foldMap (mkBinaryL  setFromList) [zero, one, tiny, small, medium] --, large]+equal    = foldMap (mkEqual    setFromList) [zero, one, tiny, small, medium] --, large]++subset :: Color -> [Case (Zebra, NoSet) Zebra NoSet]+subset c = foldMap (mkSubset setFromList c) [zero, one, tiny, small, medium] --, large]++++-- Tip/Tip combinations.+_tipTip :: [Case (Zebra, NoSet) Zebra NoSet]+_tipTip = foldMap (\(a, b, c, d) -> mkTipTip setFromList a b c d) tipsA++-- Tip/Bin combinations.+_tipBin :: [Case (Zebra, NoSet) Zebra NoSet]+_tipBin = foldMap (\(a, b, s) -> mkTipBin setFromList a b s) tipsB++++type IdT s b = Test s Zebra NoSet b b++type TreeT s = Test s Zebra NoSet Zebra NoSet++treeEq :: Zebra -> NoSet -> Bool+treeEq set no =+  case validate set of+    Valid -> setToList set == noToList no+    _     -> False++++lookupT :: IdT Word Color+lookupT = Test (==) Zebra.lookup No.lookup++lookupLT :: IdT (Word, Color) (Maybe Word)+lookupLT = Test (==) (\(k, c) -> Zebra.lookupL c k)+                     (\(k, c) -> No.lookupL c k)++findLT :: IdT (Word, Color) Word+findLT = Test (==) (\(k, c) -> Zebra.findL (maxBound - 5) c k)+                   (\(k, c) -> No.findL (maxBound - 5) c k)++lookupRT :: IdT (Word, Color) (Maybe Word)+lookupRT = Test (==) (\(k, c) -> Zebra.lookupR c k)+                     (\(k, c) -> No.lookupR c k)++findRT :: IdT (Word, Color) Word+findRT = Test (==) (\(k, c) -> Zebra.findR (maxBound - 5) c k)+                   (\(k, c) -> No.findR (maxBound - 5) c k)++++monoT :: IdT () (Maybe Color)+monoT = Test (==) ( \_ t -> case t of+                              Zebra.Mono c -> Just c+                              _            -> Nothing+                  )+                  ( \_ t -> case t of+                              No.Mono c -> Just c+                              _         -> Nothing+                  )++monoLT :: IdT Word (Maybe Color)+monoLT = Test (==) Zebra.monoL No.monoL++monoRT :: IdT Word (Maybe Color)+monoRT = Test (==) Zebra.monoR No.monoR++monoRangeT :: IdT Range (Maybe Color)+monoRangeT = Test (==) Zebra.monoRange No.monoRange++++sizeT :: No.Color -> IdT () Natural+sizeT c = Test (==) (\_ -> Zebra.size c) (\_ -> No.size c)++sizeLT :: IdT (Word, Color) Natural+sizeLT = Test (==) (uncurry $ flip Zebra.sizeL) (uncurry $ flip No.sizeL)++sizeRT :: IdT (Word, Color) Natural+sizeRT = Test (==) (uncurry $ flip Zebra.sizeR) (uncurry $ flip No.sizeR)++sizeRangeT :: IdT (Range, Color) Natural+sizeRangeT = Test (==) (uncurry $ flip Zebra.sizeRange) (uncurry $ flip No.sizeRange)++++fillLT :: TreeT (Word, Color)+fillLT = Test treeEq (uncurry Zebra.fillL) (uncurry No.fillL)++fillRT :: TreeT (Word, Color)+fillRT = Test treeEq (uncurry Zebra.fillR) (uncurry No.fillR)++fillRangeT :: TreeT (Range, Color)+fillRangeT = Test treeEq (uncurry Zebra.fillRange) (uncurry No.fillRange)++++complementT :: TreeT ()+complementT = Test treeEq (\_ -> Zebra.complement) (\_ -> No.complement)++++foldlT, foldlT' :: IdT () [(Color, Word, Word)]+foldlT  = foldlT_ Zebra.foldl+foldlT' = foldlT_ Zebra.foldl'++foldlT_+  :: (forall x. (x -> Range -> Color -> x) -> x -> Zebra -> x)+  -> IdT () [(Color, Word, Word)]+foldlT_ g =+  let f z (Range kL kR) c = (c, kL, kR) : z+  in Test (==) (\_ -> g f []) (\_ -> No.foldl f [])+++foldlLT, foldlLT' :: IdT Word [(Color, Word, Word)]+foldlLT  = foldlLT_ Zebra.foldlL+foldlLT' = foldlLT_ Zebra.foldlL'++foldlLT_+  :: (forall x. Word -> (x -> Range -> Color -> x) -> x -> Zebra -> x)+  -> IdT Word [(Color, Word, Word)]+foldlLT_ g =+  let f z (Range kL kR) c = (c, kL, kR) : z+  in Test (==) (\w -> g w f []) (\w -> No.foldlL w f [])+++foldlRT, foldlRT' :: IdT Word [(Color, Word, Word)]+foldlRT  = foldlRT_ Zebra.foldlR+foldlRT' = foldlRT_ Zebra.foldlR'++foldlRT_+  :: (forall x. Word -> (x -> Range -> Color -> x) -> x -> Zebra -> x)+  -> IdT Word [(Color, Word, Word)]+foldlRT_ g =+  let f z (Range kL kR) c = (c, kL, kR) : z+  in Test (==) (\w -> g w f []) (\w -> No.foldlR w f [])+++foldlRangeT, foldlRangeT' :: IdT Range [(Color, Word, Word)]+foldlRangeT  = foldlRangeT_ Zebra.foldlRange+foldlRangeT' = foldlRangeT_ Zebra.foldlRange'++foldlRangeT_+  :: (forall x. Range -> (x -> Range -> Color -> x) -> x -> Zebra -> x)+  -> IdT Range [(Color, Word, Word)]+foldlRangeT_ g =+  let f z (Range kL kR) c = (c, kL, kR) : z+  in Test (==) (\w -> g w f []) (\w -> No.foldlRange w f [])++++foldrT, foldrT' :: IdT () [(Color, Word, Word)]+foldrT  = foldrT_ Zebra.foldr+foldrT' = foldrT_ Zebra.foldr'++foldrT_+  :: (forall x. (Range -> Color -> x -> x) -> x -> Zebra -> x)+  -> IdT () [(Color, Word, Word)]+foldrT_ g =+  let f (Range kL kR) c = (:) (c, kL, kR)+  in Test (==) (\_ -> g f []) (\_ -> No.foldr f [])+++foldrLT, foldrLT' :: IdT Word [(Color, Word, Word)]+foldrLT  = foldrLT_ Zebra.foldrL+foldrLT' = foldrLT_ Zebra.foldrL'++foldrLT_+  :: (forall x. Word -> (Range -> Color -> x -> x) -> x -> Zebra -> x)+  -> IdT Word [(Color, Word, Word)]+foldrLT_ g =+  let f (Range kL kR) c = (:) (c, kL, kR)+  in Test (==) (\w -> g w f []) (\w -> No.foldrL w f [])+++foldrRT, foldrRT' :: IdT Word [(Color, Word, Word)]+foldrRT  = foldrRT_ Zebra.foldrR+foldrRT' = foldrRT_ Zebra.foldrR'++foldrRT_+  :: (forall x. Word -> (Range -> Color -> x -> x) -> x -> Zebra -> x)+  -> IdT Word [(Color, Word, Word)]+foldrRT_ g =+  let f (Range kL kR) c = (:) (c, kL, kR)+  in Test (==) (\w -> g w f []) (\w -> No.foldrR w f [])++++foldrRangeT, foldrRangeT' :: IdT Range [(Color, Word, Word)]+foldrRangeT  = foldrRangeT_ Zebra.foldrRange+foldrRangeT' = foldrRangeT_ Zebra.foldrRange'++foldrRangeT_+  :: (forall x. Range -> (Range -> Color -> x -> x) -> x -> Zebra -> x)+  -> IdT Range [(Color, Word, Word)]+foldrRangeT_ g =+  let f (Range kL kR) c = (:) (c, kL, kR)+  in Test (==) (\w -> g w f []) (\w -> No.foldrRange w f [])++++unionT :: Color -> TreeT (Zebra, NoSet)+unionT c = Test treeEq (Zebra.union c . fst) (No.union c . snd)++intersectionT :: Color -> TreeT (Zebra, NoSet)+intersectionT c = Test treeEq (Zebra.intersection c . fst) (No.intersection c . snd)++disjointT :: Color -> IdT (Zebra, NoSet) Bool+disjointT c = Test (==) (Zebra.disjoint c . fst) (No.disjoint c . snd)++++differenceT :: Color -> TreeT (Zebra, NoSet)+differenceT c = Test treeEq (Zebra.difference c . fst)+                            (No.difference c . snd)++symmetricDifferenceT :: Color -> TreeT (Zebra, NoSet)+symmetricDifferenceT c = Test treeEq (Zebra.symmetricDifference c . fst)+                                     (No.symmetricDifference c . snd)++++compareT :: Color -> IdT (Zebra, NoSet) No.PartialOrdering+compareT c = Test (==) (Zebra.compare c . fst) (No.compare c . snd)++++test :: Spec+test = do+  describe "Single-key" $ do+    it "lookup"           $ run unary1_ lookupT++  describe "Left" $ do+    it "monoL"            $ run unary1_ monoLT+    it "sizeL"            $ run unary1  sizeLT+    it "lookupL"          $ run unary1  lookupLT+    it "findL"            $ run unary1  findLT+    it "fillL"            $ run unary1  fillLT+    it "foldlL"           $ run unary1_ foldlLT+    it "foldlL'"          $ run unary1_ foldlLT'+    it "foldrL"           $ run unary1_ foldrLT+    it "foldrL'"          $ run unary1_ foldrLT'++  describe "Right" $ do+    it "monoR"            $ run unary1_ monoRT+    it "sizeR"            $ run unary1  sizeRT+    it "lookupR"          $ run unary1  lookupRT+    it "findR"            $ run unary1  findRT+    it "fillR"            $ run unary1  fillRT+    it "foldlR"           $ run unary1_ foldlRT+    it "foldlR'"          $ run unary1_ foldlRT'+    it "foldrR"           $ run unary1_ foldrRT+    it "foldrR'"          $ run unary1_ foldrRT'++  describe "Range" $ do+    it "monoRange"        $ run unary2_ monoRangeT+    it "sizeRange"        $ run unary2  sizeRangeT+    it "fillRange"        $ run unary2  fillRangeT+    it "foldlRange"       $ run unary2_ foldlRangeT+    it "foldlRange'"      $ run unary2_ foldlRangeT'+    it "foldrRange"       $ run unary2_ foldrRangeT+    it "foldrRange'"      $ run unary2_ foldrRangeT'++  describe "Full-tree" $ do+    it "Mono"             $ run unary0 monoT+    it "size/White"       $ run unary0 (sizeT White)+    it "size/Black"       $ run unary0 (sizeT Black)+    it "foldl"            $ run unary0 foldlT+    it "foldl'"           $ run unary0 foldlT'+    it "foldr"            $ run unary0 foldrT+    it "foldr'"           $ run unary0 foldrT'++  describe "Merge" $ do+    it "complement"                 $ run unary0  complementT+    it "union/White"                $ run binaryL (unionT White)+    it "union/Black"                $ run binaryL (unionT Black)+    it "disjoint/White"             $ run binaryL (disjointT White)+    it "disjoint/Black"             $ run binaryL (disjointT Black)+    it "intersection/White"         $ run binaryL (intersectionT White)+    it "intersection/Black"         $ run binaryL (intersectionT Black)+    it "difference/White"           $ run binaryL (differenceT White)+    it "difference/Black"           $ run binaryL (differenceT Black)+    it "symmetricDifference/White"  $ run binaryL (symmetricDifferenceT White)+    it "symmetricDifference/Black"  $ run binaryL (symmetricDifferenceT Black)++    it "compare/incomparable/White" $ run binaryL        (compareT White)+    it "compare/incomparable/Black" $ run binaryL        (compareT Black)+    it "compare/equal/White"        $ run equal          (compareT White)+    it "compare/equal/Black"        $ run equal          (compareT Black)+    it "compare/subset/White"       $ run (subset White) (compareT White)+    it "compare/subset/Black"       $ run (subset Black) (compareT Black)+    it "compare/superset/White"     $ run (subset Black) (compareT White)+    it "compare/superset/Black"     $ run (subset White) (compareT Black)
+ test/properties/Test/Zebra/Word/Sample.hs view
@@ -0,0 +1,233 @@+{-# LANGUAGE RankNTypes #-}++module Test.Zebra.Word.Sample+  ( Sample+  , zero+  , one+  , tiny+  , small+  , medium+  , large++  , mkUnary0+  , mkUnary1+  , mkUnary2++  , mkBinaryL+  , mkEqual+  , mkSubset++  , tipsA+  , mkTipTip+  , tipsB+  , mkTipBin+  ) where++import           No.Set.Word (NoSet)+import qualified No.Set.Word as No+import           Test.Kit+import           Test.Random++import           Data.Foldable (foldl')+import           Data.Function+import qualified Data.List as List+import           System.Random++++data Sample = Sample+                No.Color           -- ^ Color of negative infinity in the set+                [(Word, No.Color)] -- ^ Keys in the set (colors are arbitrary)+                [(Word, No.Color)] -- ^ Keys not in the set (colors are arbitrary)+              deriving Show++zero, one :: Sample+zero = Sample No.Black []+         [ (0, No.Black), (5824, No.White), (6183, No.Black), (maxBound, No.White)+         ]++one  = Sample No.White [(6593, No.Black)]+         [ (0   , No.Black), (4905, No.White), (6285, No.Black), (6134    , No.White)+         , (6737, No.Black), (6928, No.White), (7513, No.Black), (maxBound, No.White)+         ]++++halve :: [a] -> ([a], [a])+halve (a:b:cs) = let ~(xs, ys) = halve cs+                 in (a:xs, b:ys)+halve a        = (a, [])++color :: Bool -> No.Color+color False = No.Black+color True  = No.White++sample :: RandomGen g => (Word, Word) -> Int -> g -> (Sample, g)+sample r n g0 =+  let ~(c0, g1) = uniform g0++      ~(xs, g2) = list (\g' -> let ~(w, g'') = uniformR r g'+                                   ~(c, _)   = uniform g''++                               in ((w, color c), g'')+                       )+                    n g1++      cs = List.nub $ List.sortBy (compare `on` fst) xs++      ~(as, bs) = halve cs++  in (Sample (color c0) as bs, g2)++++-- | Function that fills the space in the \((+\infty, k]\) range with the given color.+type FillL set = Word -> No.Color -> set -> set++type FromList set = No.Color+                    -- ^ Color of positive infinity++                 -> (FillL set -> set -> set)+                    -- ^ Application of every other color.++                 -> set++foldrFromList :: FromList set -> No.Color -> [(Word, No.Color)] -> set+foldrFromList f c xs = f c (\g s0 -> List.foldr (uncurry g) s0 xs)++noFromList :: FromList NoSet+noFromList c f = f No.fillL (No.Mono c)++setFromNo :: Show set => FromList set -> NoSet -> set+setFromNo setFromList no =+  case No.foldl (\z r c -> (r, c) : z) [] no of+    []          -> error "Zebra.Sample: empty NoSet"+    (_, c) : ys -> setFromList c $ \f s -> foldl' (\z (No.Range _ b, x) -> f b x z) s ys++tiny, small, medium, large :: Sample+tiny   = fst $ sample (0x1000, 0x80000) 8    (mkStdGen 0)+small  = fst $ sample (0x1000, 0x80000) 64   (mkStdGen 1)+medium = fst $ sample (0x1000, 0x80000) 512  (mkStdGen 2)+large  = fst $ sample (0x1000, 0x80000) 4096 (mkStdGen 3)++++mkUnary0 :: FromList set -> Sample -> [Case () set NoSet]+mkUnary0 setFromList (Sample c xs _) =+  [Case () (foldrFromList setFromList c xs) (foldrFromList noFromList c xs)]++mkUnary1 :: FromList set -> Sample -> [Case (Word, No.Color) set NoSet]+mkUnary1 setFromList (Sample c xs ys) =+  let set = foldrFromList setFromList c xs+      no  = foldrFromList noFromList c xs++  in foldr (\x -> (:) (Case x set no)) [] $+       (:) (0, No.Black) . (:) (maxBound, No.White) $ xs <> ys++mkUnary2 :: FromList set -> Sample -> [Case (No.Range, No.Color) set NoSet]+mkUnary2 setFromList (Sample c xs ys) =+  let set = foldrFromList setFromList c xs+      no  = foldrFromList noFromList c xs++      ~(as, bs) = halve xs+      ~(cs, ds) = halve ys++      ones = fmap (\(a, i) -> (No.UnsafeRange a a, i)) $+               (:) (0, No.White) . (:) (maxBound, No.Black) $ as <> cs++      es = List.nub . List.sortBy (compare `on` fst) $ bs <> ds++      twos = (:) (No.UnsafeRange 0       0x65432 , No.Black)+           . (:) (No.UnsafeRange 0x54321 maxBound, No.White)+           . (:) (No.UnsafeRange 0       maxBound, No.White)+           $ unsafeRanges es++  in foldr (\x -> (:) (Case x set no)) [] $ ones <> twos+  where+    -- | Converts an ascending list of integers into a list of ranges.+    unsafeRanges :: [(Word, No.Color)] -> [(No.Range, No.Color)]+    unsafeRanges ((a, x):(b, _):cs) = (No.UnsafeRange a b, x) : unsafeRanges cs+    unsafeRanges _                  = []++++mkBinaryL :: FromList set -> Sample -> [Case (set, NoSet) set NoSet]+mkBinaryL setFromList (Sample c xs ys) =+  let set1 = foldrFromList setFromList c xs+      no1  = foldrFromList noFromList c xs++      set2 = foldrFromList setFromList c ys+      no2  = foldrFromList noFromList c ys++  in [Case (set2, no2) set1 no1]+++mkEqual :: FromList set -> Sample -> [Case (set, NoSet) set NoSet]+mkEqual setFromList (Sample c xs _) =+  let set = foldrFromList setFromList c xs+      no  = foldrFromList noFromList c xs++  in [Case (set, no) set no]++mkSubset :: Show set => FromList set -> No.Color -> Sample -> [Case (set, NoSet) set NoSet]+mkSubset setFromList x (Sample c xs ys) =+  let set = foldrFromList setFromList c xs++      no  = foldrFromList noFromList c xs+      no' = foldrFromList noFromList c ys++      noI = No.intersection x no no'++  in [Case (setFromNo setFromList noI, noI) set no]++++tipA :: RandomGen g => g -> ((No.Color, Word, No.Color, Word), g)+tipA g0 =+  let ~(c1, g1) = uniform g0+      ~(w1, g2) = uniform g1++      ~(c2, g3) = uniform g2+      ~(w2, g4) = uniform g3++  in ((if c1 then No.White else No.Black, w1, if c2 then No.White else No.Black, w2), g4)++tipsA :: [(No.Color, Word, No.Color, Word)]+tipsA = fst $ list tipA 10000 (mkStdGen 0)++mkTipTip :: FromList set -> No.Color -> Word -> No.Color -> Word -> [Case (set, NoSet) set NoSet]+mkTipTip setFromList c1 w1 c2 w2 =+  let set1 = foldrFromList setFromList c1 [(w1, No.other c1)]+      no1  = foldrFromList noFromList c1 [(w1, No.other c1)]++      set2 = foldrFromList setFromList c2 [(w2, No.other c2)]+      no2  = foldrFromList noFromList c2 [(w2, No.other c2)]++  in [Case (set2, no2) set1 no1]++++tipB :: RandomGen g => g -> ((No.Color, Word, Sample), g)+tipB g0 =+  let ~(c1, g1) = uniform g0+      ~(w1, g2) = uniform g1++      ~(s, g3) = sample (0, maxBound) 16 g2++  in ((if c1 then No.White else No.Black, w1, s), g3)++tipsB :: [(No.Color, Word, Sample)]+tipsB = fst $ list tipB 1000 (mkStdGen 0)++mkTipBin :: FromList set -> No.Color -> Word -> Sample -> [Case (set, NoSet) set NoSet]+mkTipBin setFromList c1 w1 (Sample c2 xs ys) =+  let set1 = foldrFromList setFromList c1 [(w1, No.other c1)]+      no1  = foldrFromList noFromList c1 [(w1, No.other c1)]++      set2 = foldrFromList setFromList c2 xs+      no2  = foldrFromList noFromList c2 xs++      (setA, noA, setB, noB) | (_, No.Black):_ <- ys = (set2, no2, set1, no1)+                             | otherwise             = (set1, no1, set2, no2)++  in [Case (setB, noB) setA noA]