{-# LANGUAGE FlexibleInstances #-} -- | This module implements a simple \"pure\" graph interface, destined -- to be used for the complex graph operations required by VersionDag. -- -- We instance 'Show' for debugging purposes. module Graphs.PureGraph( PureGraph(..), NodeData(..), ArcData(..), emptyPureGraph, -- :: Ord nodeInfo => PureGraph nodeInfo arcInfo addNode, -- :: Ord nodeInfo -- => PureGraph nodeInfo arcInfo -> nodeInfo -> [(arcInfo,nodeInfo)] -- -> PureGraph nodeInfo arcInfo deleteNode, -- :: Ord nodeInfo -- => PureGraph nodeInfo arcInfo -> nodeInfo -- -> PureGraph nodeInfo arcInfo mapArcInfo, -- :: (arcInfo1 -> arcInfo2) -> PureGraph nodeInfo arcInfo1 -- -> PureGraph nodeInfo arcInfo2 parentNodes, -- :: NodeData nodeInfo arcInfo -> [nodeInfo] toAllNodes, -- :: Ord nodeInfo => PureGraph nodeInfo arcInfo -> [nodeInfo] toNodeParents, -- :: Ord nodeInfo => PureGraph nodeInfo arcInfo -> nodeInfo -- -> Maybe [nodeInfo] -- returns Nothing if the node does not exist. nodeExists, -- :: PureGraph nodeInfo arcInfo -> nodeInfo -> Bool ) where import qualified Data.Map as Map import Graphs.Graph(PartialShow(..)) -- ------------------------------------------------------------------------ -- Datatypes -- ------------------------------------------------------------------------ -- | node given with their parent nodes. The parents should always come -- before their children in the list. newtype PureGraph nodeInfo arcInfo = PureGraph { nodeDataFM :: Map.Map nodeInfo (NodeData nodeInfo arcInfo) } data NodeData nodeInfo arcInfo = NodeData { parents :: [ArcData nodeInfo arcInfo] } deriving (Show,Eq,Ord) data ArcData nodeInfo arcInfo = ArcData { arcInfo :: arcInfo, target :: nodeInfo } deriving (Show,Eq,Ord) -- --------------------------------------------------------------------------- -- Instances -- --------------------------------------------------------------------------- -- The Show instances are mainly there for debugging purposes. instance (Show nodeInfo,Show arcInfo) => Show (PureGraph nodeInfo arcInfo) where show (PureGraph fm) = show (Map.toList fm) instance Show (PartialShow (PureGraph nodeInfo arcInfo)) where show (PartialShow (PureGraph fm)) = "NParents dump :" ++ show (PartialShow (Map.elems fm)) instance Show (PartialShow (NodeData nodeInfo arcInfo)) where show (PartialShow nodeData) = "#"++show (length (parents nodeData)) -- --------------------------------------------------------------------------- -- Creating and modifying graphs -- --------------------------------------------------------------------------- emptyPureGraph :: Ord nodeInfo => PureGraph nodeInfo arcInfo emptyPureGraph = PureGraph Map.empty -- | add a node with given parent arcs from it. addNode :: Ord nodeInfo => PureGraph nodeInfo arcInfo -> nodeInfo -> [(arcInfo,nodeInfo)] -> PureGraph nodeInfo arcInfo addNode (PureGraph fm) newNode newArcs = PureGraph (Map.insert newNode (NodeData {parents = map (\ (arcInfo,target) -> ArcData {arcInfo = arcInfo,target = target}) newArcs }) fm ) -- | NB. The graph will end up ill-formed if you delete a node which -- has parent arcs pointing to it. deleteNode :: Ord nodeInfo => PureGraph nodeInfo arcInfo -> nodeInfo -> PureGraph nodeInfo arcInfo deleteNode (PureGraph fm) node = PureGraph (Map.delete node fm) -- --------------------------------------------------------------------------- -- Other Elementary functions -- --------------------------------------------------------------------------- toAllNodes :: Ord nodeInfo => PureGraph nodeInfo arcInfo -> [nodeInfo] toAllNodes (PureGraph fm) = Map.keys fm toNodeParents :: Ord nodeInfo => PureGraph nodeInfo arcInfo -> nodeInfo -> Maybe [nodeInfo] toNodeParents (PureGraph fm) nodeInfo = do nodeData <- Map.lookup nodeInfo fm return (parentNodes nodeData) nodeExists :: Ord nodeInfo => PureGraph nodeInfo arcInfo -> nodeInfo -> Bool nodeExists (PureGraph fm) nodeInfo = Map.member nodeInfo fm mapArcInfo :: (arcInfo1 -> arcInfo2) -> PureGraph nodeInfo arcInfo1 -> PureGraph nodeInfo arcInfo2 mapArcInfo mapArc (PureGraph fm) = PureGraph (Map.mapWithKey (\ _ nodeData1 -> let parents1 = parents nodeData1 parents2 = map (\ arcData1 -> arcData1 {arcInfo = mapArc (arcInfo arcData1)}) parents1 in nodeData1 {parents = parents2} ) fm ) parentNodes :: NodeData nodeInfo arcInfo -> [nodeInfo] parentNodes nodeData = fmap target (parents nodeData)