-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathChainDef.hs
57 lines (41 loc) · 1.62 KB
/
ChainDef.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
{-# LANGUAGE GeneralizedNewtypeDeriving, RankNTypes #-}
module ChainDef where
import Node
import Distribution
import Data.Map as Map
import Control.Monad.State
import Control.Monad.Identity
type Graph = Map.Map NodeId AnyNode
newtype ChainDef a = ChainDef { unChainDef :: StateT NodeId (StateT Graph Identity) a }
deriving (Monad)
runChainDef :: ChainDef a -> (a, Graph)
runChainDef = (\((a, _), b) -> (a, b))
. runIdentity
. flip runStateT Map.empty
. flip runStateT 2 -- 0 and 1 reserved for source/sink
. unChainDef
newId :: ChainDef NodeId
newId = do
ChainDef get >>= \n -> ChainDef (put (n + 1)) >> return n
getGraph :: ChainDef Graph
getGraph = ChainDef (lift get)
putGraph :: Graph -> ChainDef ()
putGraph = ChainDef . lift . put
trans :: (Distribution d, SrcNode src, DstNode dest) => src -> dest -> d -> ChainDef ()
trans source target distr = do
graph <- getGraph
let newNode = addTrans (MkDestNode target, MkDistr distr) (MkSourceNode source)
putGraph $ Map.insert (nodeId (nodeInfo newNode)) (toAny newNode) graph
createNode :: NodeClass n => (NodeId -> n) -> ChainDef n
createNode newNode = do
i <- newId
graph <- getGraph
let node = newNode i
putGraph $ Map.insert i (toAny node) graph
return node
createInter :: Logged -> ChainDef Inter
createInter l = createNode (\i -> Inter (NodeInfo i l) [])
createSink :: (Distribution d) => Logged -> d -> ChainDef Sink
createSink l d = createNode (\i -> Sink (NodeInfo i l) (MkDistr d))
createSource :: Logged -> ChainDef Source
createSource l = createNode (\i -> Source (NodeInfo i l) [])