module Data.Apart.Structures.Graph (Graph, Edges (..), isolated, star, remove) where import "free" Control.Comonad.Cofree (Cofree (..), unwrap) import "comonad" Control.Comonad (Comonad (..)) import Data.Apart.Transformations (Segmented (..)) -- | Directed acyclic graph. type Graph = Cofree Edges data Edges a = Empty | Connect a | Overlay a deriving Show instance Functor Edges where fmap f Empty = Empty fmap f (Connect x) = Connect $ f x fmap f (Overlay x) = Overlay $ f x instance Foldable Edges where foldr f acc Empty = acc foldr f acc (Connect x) = f x acc foldr f acc (Overlay x) = f x acc instance Traversable Edges where traverse f Empty = pure Empty traverse f (Connect x) = Connect <$> f x traverse f (Overlay x) = Overlay <$> f x connect, overlay, empty :: Segmented Graph a -> Segmented Graph a connect = foldr (\x _ -> Connect x) Empty overlay = foldr (\x _ -> Overlay x) Empty empty = const Empty isolated :: Foldable t => t a -> Segmented Graph a isolated = foldr (\el -> Overlay . (:<) el) Empty star :: Foldable t => a -> t a -> Graph a star x structure = x :< connect (isolated structure) -- | Remove vertex and all of its edges. remove :: Eq a => a -> Graph a -> Segmented Graph a remove x graph@((==) x . extract -> True) = overlay $ unwrap graph remove x graph@(y :< segment) = ((:<) y . overlay . remove x) <$> segment -- Take a degree of focused value degree :: Graph a -> Int degree (x :< Empty) = 0 degree (x :< Overlay xs) = 0 degree (x :< Connect xs) = length xs