summaryrefslogtreecommitdiff
path: root/src/Erebos/Storage
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2026-05-30 14:25:15 +0200
committerRoman Smrž <roman.smrz@seznam.cz>2026-05-30 15:29:24 +0200
commit035a0114de75f3aa1e9e3d9c78ebd4092f309e95 (patch)
treecdbcef4c5f825b6db92a3c59c7afff39df5b26d8 /src/Erebos/Storage
parent9a5ad95a573cfe7d58ad8c72955cdda59667a639 (diff)
Graph data type to represent stored history
Diffstat (limited to 'src/Erebos/Storage')
-rw-r--r--src/Erebos/Storage/Graph.hs49
1 files changed, 47 insertions, 2 deletions
diff --git a/src/Erebos/Storage/Graph.hs b/src/Erebos/Storage/Graph.hs
index f5c37b7..7f9fbd9 100644
--- a/src/Erebos/Storage/Graph.hs
+++ b/src/Erebos/Storage/Graph.hs
@@ -16,6 +16,11 @@ module Erebos.Storage.Graph (
findPropertyFirst,
storedDifference,
+
+ Graph,
+ graphFromTips, graphRemoveTips,
+ graphSize,
+ graphToList,
) where
import Control.Concurrent.MVar
@@ -98,6 +103,9 @@ generationsBy parents xs = NE.unfoldr gen ( xs, S.fromList xs )
added -> let next = foldr S.insert cur added
in Just ( added, next )
+
+type StoredTips a = [ Stored a ]
+
-- |Returns set containing all given objects and their ancestors
ancestors :: Storable a => [Stored a] -> Set (Stored a)
ancestors = NE.last . generations
@@ -108,8 +116,8 @@ precedes x y = not $ x `elem` filterAncestors [x, y]
precedesOrEquals :: Storable a => Stored a -> Stored a -> Bool
precedesOrEquals x y = filterAncestors [ x, y ] == [ y ]
-filterAncestors :: Storable a => [Stored a] -> [Stored a]
-filterAncestors [x] = [x]
+filterAncestors :: Storable a => [ Stored a ] -> StoredTips a
+filterAncestors [ x ] = [ x ]
filterAncestors xs = let xs' = uniq $ sort xs
in helper xs' xs'
where helper remains walk = case generationMax walk of
@@ -168,3 +176,40 @@ storedDifference xs' ys' =
yg = S.toAscList $ NE.last $ generationsBy (filteredPrevious xs) $ filterAncestors (ys ++ xs) `diffSorted` xs
in xg `mergeUniq` yg
+
+
+data Graph a = Graph
+ { graphHead :: StoredTips a
+ , graphTail :: StoredTips a
+ }
+
+graphFromTips :: StoredTips a -> Graph a
+graphFromTips h = Graph h []
+
+graphRemoveTips :: Storable a => StoredTips a -> Graph a -> Graph a
+graphRemoveTips remove g =
+ let gtails = if null (graphTail g) then remove
+ else filterAncestors $ graphTail g ++ remove
+ gheads = filter (\h -> not $ any (h `precedesOrEquals`) gtails) (graphHead g)
+ in Graph { graphHead = gheads, graphTail = gtails }
+
+graphSize :: Storable a => Graph a -> Int
+graphSize = length . graphToList (\_ _ -> EQ)
+
+graphToList :: Storable a => (Stored a -> Stored a -> Ordering) -> Graph a -> [ Stored a ]
+graphToList cmp Graph {..} = go S.empty graphHead
+ where
+ go _ [] = []
+ go used (x : xs)
+ | ( x', xs' ) <- selectMax x xs
+ = x' : go (S.insert x used) (xs' ++ filter (\(p :: Stored a) -> not $ p `S.member` used || any (p `precedesOrEquals`) graphTail) (previous x))
+
+ cmp' x y = case cmp x y of EQ -> compare x y
+ o -> o
+
+ selectMax y (x : xs)
+ = case cmp' y x of
+ LT -> (y :) <$> selectMax x xs
+ EQ -> selectMax y xs
+ GT -> (x :) <$> selectMax y xs
+ selectMax y [] = ( y, [] )