packages feed

SciFlow-0.7.0: src/Control/Workflow/Interpreter/Graph.hs

{-# LANGUAGE GADTs                 #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}

module Control.Workflow.Interpreter.Graph
    ( mkGraph
    , Graph(..)
    , Node(..)
    , Edge(..)
    ) where

import           Control.Arrow (Arrow(..))
import Control.Arrow.Free (Free, eval)
import           Control.Category
import qualified Data.Text          as T
import           Prelude            hiding (id, (.))
import qualified Data.HashSet as S
import Data.Hashable (Hashable(..))

import Control.Workflow.Types

mkGraph :: SciFlow env -> Graph
mkGraph flow = Graph ns $ map (\(a,b) -> Edge (_id a) $ _id b) es
  where
    ns = S.toList $ S.fromList $ concatMap (\(a,b) -> [a,b]) es
    es = S.toList $ S.fromList $ toEdges $ toDiagram $ _flow flow
{-# INLINE mkGraph #-}

data Graph = Graph
    { _nodes :: [Node]
    , _edges :: [Edge] }

data Node = Node
    { _id :: T.Text
    , _label :: T.Text
    , _descr :: T.Text }

instance Hashable Node where
    hashWithSalt s = hashWithSalt s . _id

instance Eq Node where
    a == b = _id a == _id b

data Edge = Edge
    { _from :: T.Text
    , _to :: T.Text }

toEdges :: Diagram a b -> [(Node, Node)]
toEdges (Seq f g) = map (\[a,b] -> (a,b)) (sequence [lastD f, headD g]) ++
    toEdges f ++ toEdges g
toEdges (Par f g) = toEdges f ++ toEdges g
toEdges _ = []
{-# INLINE toEdges #-}

headD :: Diagram a b -> [Node]
headD (S nd) = [nd]
headD (Seq Ident g) = headD g
headD (Seq f _) = headD f
headD (Par f g) = headD f ++ headD g
headD _ = []
{-# INLINE headD #-}

lastD :: Diagram a b -> [Node]
lastD (S nd) = [nd]
lastD (Seq f Ident) = lastD f
lastD (Seq _ g) = lastD g
lastD (Par f g) = lastD f ++ lastD g
lastD _ = []
{-# INLINE lastD #-}

toDiagram :: Free (Flow env) a b -> Diagram a b
toDiagram = eval toDiagram'
  where
    toDiagram' (Step Job{..}) = S (Node _job_name _job_name _job_descr)
{-# INLINE toDiagram #-}
  
data Diagram a b where
    Ident :: Diagram a b
    S :: Node -> Diagram a b
    Seq :: Diagram a b -> Diagram b c -> Diagram a c
    Par :: Diagram a b -> Diagram c d -> Diagram (a,c) (b,d)
  
instance Category Diagram where
    id = Ident
    (.) = flip Seq
  
instance Arrow Diagram where
    arr = const Ident
    (***) = Par