module Haskus.Utils.STM.TGraph
( deepFirst
, breadthFirst
, TNode (..)
, singleton
, linkTo
)
where
import qualified Data.Set as Set
import Haskus.Utils.STM
import Haskus.Utils.Flow
import Haskus.Utils.STM.TList (TList)
import qualified Haskus.Utils.STM.TList as TList
deepFirst :: (Monad m, Ord a) => (a -> m ()) -> (a -> m ()) -> (a -> m [a]) -> [a] -> m ()
deepFirst before after children = foldM_ go Set.empty
where
go visited x
| Set.member x visited =
return visited
| otherwise = do
before x
cs <- children x
let visited' = Set.insert x visited
visited'' <- foldM go visited' cs
after x
return visited''
breadthFirst :: (Monad m, Ord a) => (a -> m Bool) -> (a -> m [a]) -> [a] -> m ()
breadthFirst visit children = go Set.empty
where
go _ [] =
return ()
go visited (x:xs)
| Set.member x visited =
go visited xs
| otherwise = do
b <- visit x
when b $ do
cs <- children x
go (Set.insert x visited) (xs ++ cs)
data TNode a r = TNode
{ nodeValue :: a
, nodeEdgeIn :: TList (r, TNode a r)
, nodeEdgeOut :: TList (r, TNode a r)
}
singleton :: a -> STM (TNode a r)
singleton v = TNode v <$> TList.empty <*> TList.empty
linkTo :: TNode a r -> r -> TNode a r -> STM ()
linkTo src rel dst = do
void $ TList.append (rel, src) (nodeEdgeIn dst)
void $ TList.append (rel, dst) (nodeEdgeOut src)