module Haskus.Utils.STM.TTree
( TTree (..)
, TTreePath (..)
, singleton
, addChild
, detachChild
, attachChild
, treeFollowPath
)
where
import qualified Haskus.Utils.STM.TList as TList
import Haskus.Utils.STM.TList (TList)
import Haskus.Utils.STM.TEq
import Haskus.Utils.STM
data TTree k v = TTree
{ treeKey :: k
, treeValue :: v
, treeChildren :: TList (TTree k v)
, treeParent :: TVar (Maybe (TTree k v))
}
newtype TTreePath k = TTreePath [k]
singleton :: k -> v -> STM (TTree k v)
singleton k v =
TTree k v
<$> TList.empty
<*> newTVar Nothing
addChild :: k -> v -> TTree k v -> STM (TTree k v)
addChild k v parent = do
n <- TTree k v
<$> TList.empty
<*> newTVar (Just parent)
TList.append_ n (treeChildren parent)
return n
detachChild :: TEq k => TTree k v -> STM ()
detachChild n = do
let f c = not <$> (treeKey c `teq` treeKey n)
p <- readTVar (treeParent n)
mapM_ (TList.filter f . treeChildren) p
writeTVar (treeParent n) Nothing
attachChild :: TEq k => TTree k v -> TTree k v -> STM ()
attachChild newparent child = do
detachChild child
TList.append_ child (treeChildren newparent)
writeTVar (treeParent child) (Just newparent)
treeFollowPath :: TEq k => TTree k v -> TTreePath k -> STM (Maybe (TTree k v))
treeFollowPath p (TTreePath []) = return (Just p)
treeFollowPath p (TTreePath (x:xs)) = do
child <- TList.find (\y -> x `teq` treeKey y) (treeChildren p)
case TList.value <$> child of
Just c -> treeFollowPath c (TTreePath xs)
Nothing -> return Nothing