Add a Graph module with a graph zipper

This commit is contained in:
Tissevert 2019-05-05 12:27:50 +02:00
parent 199df91c71
commit 98c06b95ce
2 changed files with 77 additions and 1 deletions

View File

@ -18,9 +18,11 @@ build-type: Simple
extra-source-files: CHANGELOG.md
library
exposed-modules: Stream
exposed-modules: Graph
, Stream
-- other-modules:
-- other-extensions:
build-depends: base >=4.9 && <4.13
, containers
hs-source-dirs: src
default-language: Haskell2010

74
src/Graph.hs Normal file
View File

@ -0,0 +1,74 @@
{-# LANGUAGE NamedFieldPuns #-}
module Graph (
Graph(..)
) where
import Data.Map (Map, (!?))
import qualified Data.Map as Map (delete, empty, insert)
data Vertex label edge = Vertex {
label :: label
, edges :: Map edge (Vertex label edge)
} deriving Show
singleton :: label -> Vertex label edge
singleton label = Vertex {label, edges = Map.empty}
data Zipper label edge = Top | Zipper {
origin :: Zipper label edge
, from :: label
, by :: edge
, siblingEdges :: Map edge (Vertex label edge)
} deriving Show
data Graph label edge = Graph {
focus :: Vertex label edge
, context :: Zipper label edge
} deriving Show
open :: Vertex label edge -> Graph label edge
open focus = Graph {focus, context = Top}
zipUp :: Ord edge => Graph label edge -> Vertex label edge
zipUp graph =
case context graph of
Top -> focus graph
Zipper {origin, from, by, siblingEdges} -> zipUp $ Graph {
context = origin
, focus = Vertex {
label = from
, edges = Map.insert by (focus graph) siblingEdges
}
}
rewind :: Ord edge => Graph label edge -> Graph label edge
rewind = open . zipUp
follow :: Ord edge => Graph label edge -> edge -> Maybe (Graph label edge)
follow (Graph {focus, context}) edge =
edges focus !? edge >>= \vertex -> Just $ Graph {
focus = vertex
, context = Zipper {
origin = context
, from = label $ focus
, by = edge
, siblingEdges = Map.delete edge $ edges focus
}
}
weave :: (Monoid label, Ord edge) => Graph label edge -> [edge] -> Graph label edge
weave = foldl $ \graph edge ->
case graph `follow` edge of
Nothing -> Graph {
focus = singleton mempty
, context = Zipper {
origin = context graph
, from = label $ focus graph
, by = edge
, siblingEdges = edges $ focus graph
}
}
Just newGraph -> newGraph
setLabel :: Graph label edge -> label -> Graph label edge
setLabel graph newLabel = graph {focus = (focus graph) {label = newLabel}}