module Data.BTree.Pure (
module Data.BTree.Pure.Setup
, Tree(..)
, Node(..)
, empty
, singleton
, fromList
, insert
, insertMany
, delete
, lookup
, findWithDefault
, member
, notMember
, null
, size
, foldrWithKey
, toList
) where
import Prelude hiding (lookup, null)
import Data.BTree.Primitives.Exception
import Data.BTree.Primitives.Height
import Data.BTree.Primitives.Index
import Data.BTree.Primitives.Key
import Data.BTree.Primitives.Leaf
import Data.BTree.Pure.Setup
import Data.Map (Map)
import Data.Maybe (isJust, isNothing, fromMaybe)
import Data.Monoid
import qualified Data.Foldable as F
import qualified Data.List as L
import qualified Data.Map as M
data Tree key val where
Tree :: !TreeSetup
-> Maybe (Node height key val)
-> Tree key val
data Node (height :: Nat) key val where
Idx :: { idxChildren :: Index key (Node height key val)
} -> Node ('S height) key val
Leaf :: { leafItems :: Map key val
} -> Node 'Z key val
deriving instance (Show key, Show val) => Show (Node height key val)
deriving instance (Show key, Show val) => Show (Tree key val)
empty :: TreeSetup -> Tree key val
empty setup = Tree setup Nothing
singleton :: Key k => TreeSetup -> k -> v -> Tree k v
singleton s k v = insert k v (empty s)
fromList :: Key k => TreeSetup -> [(k,v)] -> Tree k v
fromList s = L.foldl' (flip $ uncurry insert) (empty s)
insert :: Key k => k -> v -> Tree k v -> Tree k v
insert k d (Tree setup (Just rootNode))
| newRootIdx <- insertRec setup k d rootNode
= case fromSingletonIndex newRootIdx of
Just newRootNode ->
Tree setup (Just newRootNode)
Nothing ->
Tree setup (Just (Idx newRootIdx))
insert k d (Tree setup Nothing)
=
Tree setup (Just (Leaf (M.singleton k d)))
insertRec :: Key key
=> TreeSetup
-> key
-> val
-> Node height key val
-> Index key (Node height key val)
insertRec setup key val (Idx children)
|
(ctx, child) <- valView key children
, newChildIdx <- insertRec setup key val child
=
splitIndex setup (putIdx ctx newChildIdx)
insertRec setup key val (Leaf items)
= splitLeaf setup (M.insert key val items)
insertMany :: Key k => Map k v -> Tree k v -> Tree k v
insertMany kvs (Tree setup (Just rootNode))
= fixUp setup $ insertRecMany setup kvs rootNode
insertMany kvs (Tree setup Nothing)
= fixUp setup $ splitLeaf setup kvs
insertRecMany :: Key key
=> TreeSetup
-> Map key val
-> Node height key val
-> Index key (Node height key val)
insertRecMany setup kvs (Idx idx)
| M.null kvs
= singletonIndex (Idx idx)
| dist <- distribute kvs idx
= splitIndex setup (dist `bindIndex` uncurry (insertRecMany setup))
insertRecMany setup kvs (Leaf items)
= splitLeaf setup (M.union kvs items)
fixUp :: Key key
=> TreeSetup
-> Index key (Node height key val)
-> Tree key val
fixUp setup idx = case fromSingletonIndex idx of
Just newRootNode -> Tree setup (Just newRootNode)
Nothing -> fixUp setup (splitIndex setup idx)
foldrWithKey :: forall k v w. (k -> v -> w -> w) -> w -> Tree k v -> w
foldrWithKey f z0 (Tree _ mbRoot) = maybe z0 (go z0) mbRoot
where
go :: w -> Node h k v -> w
go z1 (Leaf items) = M.foldrWithKey f z1 items
go z1 (Idx index) = F.foldr (flip go) z1 index
toList :: Tree k v -> [(k,v)]
toList = foldrWithKey (\k v kvs -> (k,v):kvs) []
delete :: Key k => k -> Tree k v -> Tree k v
delete _key (Tree setup Nothing) = Tree setup Nothing
delete key (Tree setup (Just rootNode)) = case deleteRec setup key rootNode of
Idx index
| Just childNode <- fromSingletonIndex index -> Tree setup (Just childNode)
Leaf items
| M.null items -> Tree setup Nothing
newRootNode -> Tree setup (Just newRootNode)
deleteRec :: Key k
=> TreeSetup
-> k
-> Node n k v
-> Node n k v
deleteRec setup key (Idx children)
| childNeedsMerge, Just (rKey, rChild, rCtx) <- rightView ctx
= Idx (putIdx rCtx (mergeNodes setup newChild rKey rChild))
| childNeedsMerge, Just (lCtx, lChild, lKey) <- leftView ctx
= Idx (putIdx lCtx (mergeNodes setup lChild lKey newChild))
| childNeedsMerge
= throw $ TreeAlgorithmError "deleteRec"
"constraint violation, found an index node with a single child"
| otherwise = Idx (putVal ctx newChild)
where
(ctx, child) = valView key children
newChild = deleteRec setup key child
childNeedsMerge = nodeNeedsMerge setup newChild
deleteRec _ key (Leaf items)
= Leaf (M.delete key items)
nodeNeedsMerge :: TreeSetup -> Node height key value -> Bool
nodeNeedsMerge setup = \case
Idx children -> indexNumKeys children < minIdxKeys setup
Leaf items -> M.size items < minLeafItems setup
mergeNodes :: Key key
=> TreeSetup
-> Node height key val
-> key
-> Node height key val
-> Index key (Node height key val)
mergeNodes setup (Leaf leftItems) _middleKey (Leaf rightItems) =
splitLeaf setup (leftItems <> rightItems)
mergeNodes setup (Idx leftIdx) middleKey (Idx rightIdx) =
splitIndex setup (mergeIndex leftIdx middleKey rightIdx)
lookupRec :: Key key
=> key
-> Node height key val
-> Maybe val
lookupRec key (Idx children)
| (_, childNode) <- valView key children
= lookupRec key childNode
lookupRec key (Leaf items)
= M.lookup key items
lookup :: Key k => k -> Tree k v -> Maybe v
lookup _ (Tree _ Nothing) = Nothing
lookup k (Tree _ (Just n)) = lookupRec k n
findWithDefault :: Key k => v -> k -> Tree k v -> v
findWithDefault v k = fromMaybe v . lookup k
member :: Key k => k -> Tree k v -> Bool
member k = isJust . lookup k
notMember :: Key k => k -> Tree k v -> Bool
notMember k = isNothing . lookup k
null :: Tree k v -> Bool
null (Tree _ n) = isNothing n
sizeNode :: Node n k v -> Int
sizeNode (Leaf items) = M.size items
sizeNode (Idx nodes) = F.sum (fmap sizeNode nodes)
size :: Tree k v -> Int
size (Tree _ Nothing) = 0
size (Tree _ (Just n)) = sizeNode n
instance F.Foldable (Tree key) where
foldMap _ (Tree _ Nothing) = mempty
foldMap f (Tree _ (Just n)) = F.foldMap f n
instance F.Foldable (Node height key) where
foldMap f (Idx idx) =
F.foldMap (F.foldMap f) idx
foldMap f (Leaf items) = F.foldMap f items
splitIndex :: TreeSetup
-> Index key (Node height key val)
-> Index key (Node ('S height) key val)
splitIndex setup = extendedIndex (maxIdxKeys setup) Idx
splitLeaf :: Key key
=> TreeSetup
-> Map key val
-> Index key (Node 'Z key val)
splitLeaf setup = splitLeafMany (maxLeafItems setup) Leaf