    {-# LANGUAGE CPP, FlexibleInstances, MultiParamTypeClasses #-}

    {- |
       Module      : Data.GraphViz.Types.Monadic
       Description : A monadic interface for making Dot graphs.
       Copyright   : (c) Ivan Lazar Miljenovic
       License     : 3-Clause BSD-style
       Maintainer  : Ivan.Miljenovic@gmail.com

       This module is based upon the /dotgen/ library by Andy Gill:
       <http://hackage.haskell.org/package/dotgen>

       It provides a monadic interface for constructing generalised Dot
       graphs.  Note that this does /not/ have an instance for @DotRepr@
       (e.g. what would be the point of the @fromCanonical@ function, as
       you can't do anything with the result): it is purely for
       construction purposes.  Use the generalised Dot graph instance for
       printing, etc.

       Note that the generalised Dot graph types are /not/ re-exported, in
       case it causes a clash with other modules you may choose to import.

       The example graph in "Data.GraphViz.Types" can be written as:

       > digraph (Str "G") $ do
       >
       >    cluster (Int 0) $ do
       >        graphAttrs [style filled, color LightGray]
       >        nodeAttrs [style filled, color White]
       >        "a0" --> "a1"
       >        "a1" --> "a2"
       >        "a2" --> "a3"
       >        graphAttrs [textLabel "process #1"]
       >
       >    cluster (Int 1) $ do
       >        nodeAttrs [style filled]
       >        "b0" --> "b1"
       >        "b1" --> "b2"
       >        "b2" --> "b3"
       >        graphAttrs [textLabel "process #2", color Blue]
       >
       >    "start" --> "a0"
       >    "start" --> "b0"
       >    "a1" --> "b3"
       >    "b2" --> "a3"
       >    "a3" --> "end"
       >    "b3" --> "end"
       >
       >    node "start" [shape MDiamond]
       >    node "end" [shape MSquare]

     -}
    module Data.GraphViz.Types.Monadic
           ( Dot
           , DotM
           , GraphID(..)
             -- * Creating a generalised DotGraph.
           , digraph
           , digraph'
           , graph
           , graph'
             -- * Adding global attributes.
           , graphAttrs
           , nodeAttrs
           , edgeAttrs
             -- * Adding items to the graph.
             -- ** Subgraphs and clusters
           , subgraph
           , anonSubgraph
           , cluster
             -- ** Nodes
           , node
           , node'
             -- ** Edges
             -- $edges
           , edge
           , (-->)
           , (<->)
           ) where

    import Data.GraphViz.Attributes        (Attributes)
    import Data.GraphViz.Types.Generalised

    import           Data.DList    (DList)
    import qualified Data.DList    as DL
    import qualified Data.Sequence as Seq

    #if !(MIN_VERSION_base (4,8,0))
    import Control.Applicative (Applicative(..))
    import Data.Monoid         (Monoid(..))
    #endif

    #if MIN_VERSION_base (4,9,0) && !MIN_VERSION_base (4,13,0)
    import Data.Semigroup (Semigroup(..))
    #endif

    import Control.Monad.Fix (MonadFix (mfix))

    -- -----------------------------------------------------------------------------
    -- The Dot monad.

    -- | The monadic representation of a Dot graph.
    type Dot n = DotM n ()

    -- | The actual monad; as with 'Dot' but allows you to return a value
    --   within the do-block.  The actual implementation is based upon the
    --   Writer monad.
    newtype DotM n a = DotM { forall n a. DotM n a -> (a, DotStmts n)
    runDot :: (a, DotStmts n) }

    execDot :: DotM n a -> DotStmts n
    execDot :: forall n a. DotM n a -> DotStmts n
    execDot = (a, DotStmts n) -> DotStmts n
    forall a b. (a, b) -> b
    snd ((a, DotStmts n) -> DotStmts n)
    -> (DotM n a -> (a, DotStmts n)) -> DotM n a -> DotStmts n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DotM n a -> (a, DotStmts n)
    forall n a. DotM n a -> (a, DotStmts n)
    runDot

    instance Functor (DotM n) where
      fmap :: forall a b. (a -> b) -> DotM n a -> DotM n b
    fmap a -> b
    f (DotM (a
    a,DotStmts n
    stmts)) = (b, DotStmts n) -> DotM n b
    forall n a. (a, DotStmts n) -> DotM n a
    DotM (a -> b
    f a
    a, DotStmts n
    stmts)

    instance Applicative (DotM n) where
      pure :: forall a. a -> DotM n a
    pure = (a, DotStmts n) -> DotM n a
    forall n a. (a, DotStmts n) -> DotM n a
    DotM ((a, DotStmts n) -> DotM n a)
    -> (a -> (a, DotStmts n)) -> a -> DotM n a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a -> DotStmts n -> (a, DotStmts n))
    -> DotStmts n -> a -> (a, DotStmts n)
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (,) DotStmts n
    forall a. DList a
    DL.empty

      (DotM (a -> b
    f,DotStmts n
    stmts1)) <*> :: forall a b. DotM n (a -> b) -> DotM n a -> DotM n b
    <*> (DotM (a
    a,DotStmts n
    stmts2)) = (b, DotStmts n) -> DotM n b
    forall n a. (a, DotStmts n) -> DotM n a
    DotM (a -> b
    f a
    a, DotStmts n
    stmts1 DotStmts n -> DotStmts n -> DotStmts n
    forall a. DList a -> DList a -> DList a
    `DL.append` DotStmts n
    stmts2)

    instance Monad (DotM n) where
      return :: forall a. a -> DotM n a
    return = a -> DotM n a
    forall a. a -> DotM n a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure

      DotM n a
    dt >>= :: forall a b. DotM n a -> (a -> DotM n b) -> DotM n b
    >>= a -> DotM n b
    f = (b, DotStmts n) -> DotM n b
    forall n a. (a, DotStmts n) -> DotM n a
    DotM
                 ((b, DotStmts n) -> DotM n b) -> (b, DotStmts n) -> DotM n b
    forall a b. (a -> b) -> a -> b
    $ let ~(a
    a,DotStmts n
    stmts)  = DotM n a -> (a, DotStmts n)
    forall n a. DotM n a -> (a, DotStmts n)
    runDot DotM n a
    dt
                       ~(b
    b,DotStmts n
    stmts') = DotM n b -> (b, DotStmts n)
    forall n a. DotM n a -> (a, DotStmts n)
    runDot (DotM n b -> (b, DotStmts n)) -> DotM n b -> (b, DotStmts n)
    forall a b. (a -> b) -> a -> b
    $ a -> DotM n b
    f a
    a
                   in (b
    b, DotStmts n
    stmts DotStmts n -> DotStmts n -> DotStmts n
    forall a. DList a -> DList a -> DList a
    `DL.append` DotStmts n
    stmts')

    instance MonadFix (DotM n) where
      mfix :: forall a. (a -> DotM n a) -> DotM n a
    mfix a -> DotM n a
    m = let (a
    a,DotStmts n
    n) = DotM n a -> (a, DotStmts n)
    forall n a. DotM n a -> (a, DotStmts n)
    runDot (DotM n a -> (a, DotStmts n)) -> DotM n a -> (a, DotStmts n)
    forall a b. (a -> b) -> a -> b
    $ a -> DotM n a
    m a
    a
               in  (a, DotStmts n) -> DotM n a
    forall n a. (a, DotStmts n) -> DotM n a
    DotM (a
    a,DotStmts n
    n)

    #if MIN_VERSION_base (4,9,0)
    instance Semigroup a => Semigroup (DotM n a) where
      DotM (a, DotStmts n)
    x1 <> :: DotM n a -> DotM n a -> DotM n a
    <> DotM (a, DotStmts n)
    x2 = (a, DotStmts n) -> DotM n a
    forall n a. (a, DotStmts n) -> DotM n a
    DotM ((a, DotStmts n)
    x1 (a, DotStmts n) -> (a, DotStmts n) -> (a, DotStmts n)
    forall a. Semigroup a => a -> a -> a
    <> (a, DotStmts n)
    x2)
    #endif

    instance Monoid a => Monoid (DotM n a) where
      mappend :: DotM n a -> DotM n a -> DotM n a
    mappend (DotM (a, DotStmts n)
    x1) (DotM (a, DotStmts n)
    x2) = (a, DotStmts n) -> DotM n a
    forall n a. (a, DotStmts n) -> DotM n a
    DotM ((a, DotStmts n) -> (a, DotStmts n) -> (a, DotStmts n)
    forall a. Monoid a => a -> a -> a
    mappend (a, DotStmts n)
    x1 (a, DotStmts n)
    x2)
      mempty :: DotM n a
    mempty = (a, DotStmts n) -> DotM n a
    forall n a. (a, DotStmts n) -> DotM n a
    DotM (a, DotStmts n)
    forall a. Monoid a => a
    mempty

    tell :: DotStmts n -> Dot n
    tell :: forall n. DotStmts n -> Dot n
    tell = ((), DotStmts n) -> DotM n ()
    forall n a. (a, DotStmts n) -> DotM n a
    DotM (((), DotStmts n) -> DotM n ())
    -> (DotStmts n -> ((), DotStmts n)) -> DotStmts n -> DotM n ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (,) ()

    tellStmt :: DotStmt n -> Dot n
    tellStmt :: forall n. DotStmt n -> Dot n
    tellStmt = DotStmts n -> Dot n
    forall n. DotStmts n -> Dot n
    tell (DotStmts n -> Dot n)
    -> (DotStmt n -> DotStmts n) -> DotStmt n -> Dot n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DotStmt n -> DotStmts n
    forall a. a -> DList a
    DL.singleton

    -- -----------------------------------------------------------------------------
    -- Creating the DotGraph

    -- | Create a directed dot graph with the specified graph ID.
    digraph :: GraphID -> DotM n a -> DotGraph n
    digraph :: forall n a. GraphID -> DotM n a -> DotGraph n
    digraph = Bool -> Maybe GraphID -> DotM n a -> DotGraph n
    forall n a. Bool -> Maybe GraphID -> DotM n a -> DotGraph n
    mkGraph Bool
    True (Maybe GraphID -> DotM n a -> DotGraph n)
    -> (GraphID -> Maybe GraphID) -> GraphID -> DotM n a -> DotGraph n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GraphID -> Maybe GraphID
    forall a. a -> Maybe a
    Just

    -- | Create a directed dot graph with no graph ID.
    digraph' :: DotM n a -> DotGraph n
    digraph' :: forall n a. DotM n a -> DotGraph n
    digraph' = Bool -> Maybe GraphID -> DotM n a -> DotGraph n
    forall n a. Bool -> Maybe GraphID -> DotM n a -> DotGraph n
    mkGraph Bool
    True Maybe GraphID
    forall a. Maybe a
    Nothing

    -- | Create a undirected dot graph with the specified graph ID.
    graph :: GraphID -> DotM n a -> DotGraph n
    graph :: forall n a. GraphID -> DotM n a -> DotGraph n
    graph = Bool -> Maybe GraphID -> DotM n a -> DotGraph n
    forall n a. Bool -> Maybe GraphID -> DotM n a -> DotGraph n
    mkGraph Bool
    False (Maybe GraphID -> DotM n a -> DotGraph n)
    -> (GraphID -> Maybe GraphID) -> GraphID -> DotM n a -> DotGraph n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GraphID -> Maybe GraphID
    forall a. a -> Maybe a
    Just

    -- | Create a undirected dot graph with no graph ID.
    graph' :: DotM n a -> DotGraph n
    graph' :: forall n a. DotM n a -> DotGraph n
    graph' = Bool -> Maybe GraphID -> DotM n a -> DotGraph n
    forall n a. Bool -> Maybe GraphID -> DotM n a -> DotGraph n
    mkGraph Bool
    False Maybe GraphID
    forall a. Maybe a
    Nothing

    mkGraph :: Bool -> Maybe GraphID -> DotM n a -> DotGraph n
    mkGraph :: forall n a. Bool -> Maybe GraphID -> DotM n a -> DotGraph n
    mkGraph Bool
    isDir Maybe GraphID
    mid DotM n a
    dot = DotGraph { strictGraph :: Bool
    strictGraph     = Bool
    False
                                     , directedGraph :: Bool
    directedGraph   = Bool
    isDir
                                     , graphID :: Maybe GraphID
    graphID         = Maybe GraphID
    mid
                                     , graphStatements :: DotStatements n
    graphStatements = DotM n a -> DotStatements n
    forall n a. DotM n a -> DotStatements n
    execStmts DotM n a
    dot
                                     }

    -- -----------------------------------------------------------------------------
    -- Statements

    type DotStmts n = DList (DotStmt n)

    execStmts :: DotM n a -> DotStatements n
    execStmts :: forall n a. DotM n a -> DotStatements n
    execStmts = DotStmts n -> DotStatements n
    forall n. DotStmts n -> DotStatements n
    convertStatements (DotStmts n -> DotStatements n)
    -> (DotM n a -> DotStmts n) -> DotM n a -> DotStatements n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DotM n a -> DotStmts n
    forall n a. DotM n a -> DotStmts n
    execDot

    convertStatements :: DotStmts n -> DotStatements n
    convertStatements :: forall n. DotStmts n -> DotStatements n
    convertStatements = [DotStatement n] -> Seq (DotStatement n)
    forall a. [a] -> Seq a
    Seq.fromList ([DotStatement n] -> Seq (DotStatement n))
    -> (DotStmts n -> [DotStatement n])
    -> DotStmts n
    -> Seq (DotStatement n)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (DotStmt n -> DotStatement n) -> [DotStmt n] -> [DotStatement n]
    forall a b. (a -> b) -> [a] -> [b]
    map DotStmt n -> DotStatement n
    forall n. DotStmt n -> DotStatement n
    convertStatement ([DotStmt n] -> [DotStatement n])
    -> (DotStmts n -> [DotStmt n]) -> DotStmts n -> [DotStatement n]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DotStmts n -> [DotStmt n]
    forall a. DList a -> [a]
    DL.toList

    data DotStmt n = MA GlobalAttributes
                   | MS (Subgraph n)
                   | MN (DotNode n)
                   | ME (DotEdge n)

    convertStatement          :: DotStmt n -> DotStatement n
    convertStatement :: forall n. DotStmt n -> DotStatement n
    convertStatement (MA GlobalAttributes
    gas) = GlobalAttributes -> DotStatement n
    forall n. GlobalAttributes -> DotStatement n
    GA GlobalAttributes
    gas
    convertStatement (MS Subgraph n
    sg)  = DotSubGraph n -> DotStatement n
    forall n. DotSubGraph n -> DotStatement n
    SG (DotSubGraph n -> DotStatement n)
    -> (DotM n () -> DotSubGraph n) -> DotM n () -> DotStatement n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Bool -> Maybe GraphID -> DotStatements n -> DotSubGraph n
    forall n. Bool -> Maybe GraphID -> DotStatements n -> DotSubGraph n
    DotSG (Subgraph n -> Bool
    forall n. Subgraph n -> Bool
    sgIsClust Subgraph n
    sg) (Subgraph n -> Maybe GraphID
    forall n. Subgraph n -> Maybe GraphID
    sgID Subgraph n
    sg)
                                     (DotStatements n -> DotSubGraph n)
    -> (DotM n () -> DotStatements n) -> DotM n () -> DotSubGraph n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DotM n () -> DotStatements n
    forall n a. DotM n a -> DotStatements n
    execStmts (DotM n () -> DotStatement n) -> DotM n () -> DotStatement n
    forall a b. (a -> b) -> a -> b
    $ Subgraph n -> DotM n ()
    forall n. Subgraph n -> Dot n
    sgStmts Subgraph n
    sg
    convertStatement (MN DotNode n
    dn)  = DotNode n -> DotStatement n
    forall n. DotNode n -> DotStatement n
    DN DotNode n
    dn
    convertStatement (ME DotEdge n
    de)  = DotEdge n -> DotStatement n
    forall n. DotEdge n -> DotStatement n
    DE DotEdge n
    de

    -- -----------------------------------------------------------------------------
    -- Global Attributes

    -- | Add graph\/sub-graph\/cluster attributes.
    graphAttrs :: Attributes -> Dot n
    graphAttrs :: forall n. Attributes -> Dot n
    graphAttrs = DotStmt n -> Dot n
    forall n. DotStmt n -> Dot n
    tellStmt (DotStmt n -> Dot n)
    -> (Attributes -> DotStmt n) -> Attributes -> Dot n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GlobalAttributes -> DotStmt n
    forall n. GlobalAttributes -> DotStmt n
    MA (GlobalAttributes -> DotStmt n)
    -> (Attributes -> GlobalAttributes) -> Attributes -> DotStmt n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Attributes -> GlobalAttributes
    GraphAttrs

    -- | Add global node attributes.
    nodeAttrs :: Attributes -> Dot n
    nodeAttrs :: forall n. Attributes -> Dot n
    nodeAttrs = DotStmt n -> Dot n
    forall n. DotStmt n -> Dot n
    tellStmt (DotStmt n -> Dot n)
    -> (Attributes -> DotStmt n) -> Attributes -> Dot n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GlobalAttributes -> DotStmt n
    forall n. GlobalAttributes -> DotStmt n
    MA (GlobalAttributes -> DotStmt n)
    -> (Attributes -> GlobalAttributes) -> Attributes -> DotStmt n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Attributes -> GlobalAttributes
    NodeAttrs

    -- | Add global edge attributes
    edgeAttrs :: Attributes -> Dot n
    edgeAttrs :: forall n. Attributes -> Dot n
    edgeAttrs = DotStmt n -> Dot n
    forall n. DotStmt n -> Dot n
    tellStmt (DotStmt n -> Dot n)
    -> (Attributes -> DotStmt n) -> Attributes -> Dot n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GlobalAttributes -> DotStmt n
    forall n. GlobalAttributes -> DotStmt n
    MA (GlobalAttributes -> DotStmt n)
    -> (Attributes -> GlobalAttributes) -> Attributes -> DotStmt n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Attributes -> GlobalAttributes
    EdgeAttrs

    -- -----------------------------------------------------------------------------
    -- Subgraphs (including Clusters)

    data Subgraph n = Sg { forall n. Subgraph n -> Bool
    sgIsClust :: Bool
                         , forall n. Subgraph n -> Maybe GraphID
    sgID      :: Maybe GraphID
                         , forall n. Subgraph n -> Dot n
    sgStmts   :: Dot n
                         }

    -- | Add a named subgraph to the graph.
    subgraph :: GraphID -> DotM n a -> Dot n
    subgraph :: forall n a. GraphID -> DotM n a -> Dot n
    subgraph = Maybe GraphID -> DotM n a -> Dot n
    forall n a. Maybe GraphID -> DotM n a -> Dot n
    nonClust (Maybe GraphID -> DotM n a -> Dot n)
    -> (GraphID -> Maybe GraphID) -> GraphID -> DotM n a -> Dot n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GraphID -> Maybe GraphID
    forall a. a -> Maybe a
    Just

    -- | Add an anonymous subgraph to the graph.
    --
    --   It is highly recommended you use 'subgraph' instead.
    anonSubgraph :: DotM n a -> Dot n
    anonSubgraph :: forall n a. DotM n a -> Dot n
    anonSubgraph = Maybe GraphID -> DotM n a -> Dot n
    forall n a. Maybe GraphID -> DotM n a -> Dot n
    nonClust Maybe GraphID
    forall a. Maybe a
    Nothing

    nonClust :: Maybe GraphID -> DotM n a -> Dot n
    nonClust :: forall n a. Maybe GraphID -> DotM n a -> Dot n
    nonClust = Bool -> Maybe GraphID -> DotM n a -> Dot n
    forall n a. Bool -> Maybe GraphID -> DotM n a -> Dot n
    createSubGraph Bool
    False

    createSubGraph :: Bool -> Maybe GraphID -> DotM n a -> Dot n
    createSubGraph :: forall n a. Bool -> Maybe GraphID -> DotM n a -> Dot n
    createSubGraph Bool
    isCl Maybe GraphID
    mid = DotStmt n -> Dot n
    forall n. DotStmt n -> Dot n
    tellStmt (DotStmt n -> Dot n)
    -> (DotM n a -> DotStmt n) -> DotM n a -> Dot n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Subgraph n -> DotStmt n
    forall n. Subgraph n -> DotStmt n
    MS (Subgraph n -> DotStmt n)
    -> (DotM n a -> Subgraph n) -> DotM n a -> DotStmt n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Bool -> Maybe GraphID -> Dot n -> Subgraph n
    forall n. Bool -> Maybe GraphID -> Dot n -> Subgraph n
    Sg Bool
    isCl Maybe GraphID
    mid (Dot n -> Subgraph n)
    -> (DotM n a -> Dot n) -> DotM n a -> Subgraph n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (DotM n a -> Dot n -> Dot n
    forall a b. DotM n a -> DotM n b -> DotM n b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> () -> Dot n
    forall a. a -> DotM n a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ())

    -- | Add a named cluster to the graph.
    cluster :: GraphID -> DotM n a -> Dot n
    cluster :: forall n a. GraphID -> DotM n a -> Dot n
    cluster = Bool -> Maybe GraphID -> DotM n a -> Dot n
    forall n a. Bool -> Maybe GraphID -> DotM n a -> Dot n
    createSubGraph Bool
    True (Maybe GraphID -> DotM n a -> Dot n)
    -> (GraphID -> Maybe GraphID) -> GraphID -> DotM n a -> Dot n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GraphID -> Maybe GraphID
    forall a. a -> Maybe a
    Just

    -- -----------------------------------------------------------------------------
    -- Nodes

    -- | Add a node to the graph.
    node   :: n -> Attributes -> Dot n
    node :: forall n. n -> Attributes -> Dot n
    node n
    n = DotStmt n -> Dot n
    forall n. DotStmt n -> Dot n
    tellStmt (DotStmt n -> Dot n)
    -> (Attributes -> DotStmt n) -> Attributes -> Dot n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DotNode n -> DotStmt n
    forall n. DotNode n -> DotStmt n
    MN (DotNode n -> DotStmt n)
    -> (Attributes -> DotNode n) -> Attributes -> DotStmt n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . n -> Attributes -> DotNode n
    forall n. n -> Attributes -> DotNode n
    DotNode n
    n

    -- | Add a node with no attributes to the graph.
    node' :: n -> Dot n
    node' :: forall n. n -> Dot n
    node' = (n -> Attributes -> Dot n
    forall n. n -> Attributes -> Dot n
    `node` [])

    -- -----------------------------------------------------------------------------
    -- Edges

    {- $edges

       If you wish to use something analogous to Dot's ability to write
       multiple edges with in-line subgraphs such as:

       > {a b c} -> {d e f}

       Then you can use '-->' and '<->' in combination with monadic
       traversal functions such as @traverse_@, @for_@, @mapM_@, @forM_@
       and @zipWithM_@; for example:

       > ("a" -->) `traverse_` ["d", "e", "f"]
       > ["a", "b", "c"] `for_` (--> "d")
       > zipWithM_ (-->) ["a", "b", "c"] ["d", "e", "f"]

     -}

    -- | Add an edge to the graph.
    edge     :: n -> n -> Attributes -> Dot n
    edge :: forall n. n -> n -> Attributes -> Dot n
    edge n
    f n
    t = DotStmt n -> Dot n
    forall n. DotStmt n -> Dot n
    tellStmt (DotStmt n -> Dot n)
    -> (Attributes -> DotStmt n) -> Attributes -> Dot n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DotEdge n -> DotStmt n
    forall n. DotEdge n -> DotStmt n
    ME (DotEdge n -> DotStmt n)
    -> (Attributes -> DotEdge n) -> Attributes -> DotStmt n
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . n -> n -> Attributes -> DotEdge n
    forall n. n -> n -> Attributes -> DotEdge n
    DotEdge n
    f n
    t

    -- | Add an edge with no attributes.
    (-->) :: n -> n -> Dot n
    n
    f --> :: forall n. n -> n -> Dot n
    --> n
    t = n -> n -> Attributes -> Dot n
    forall n. n -> n -> Attributes -> Dot n
    edge n
    f n
    t []

    infixr 9 -->

    -- | An alias for '-->' to make edges look more undirected.
    (<->) :: n -> n -> Dot n
    <-> :: forall n. n -> n -> Dot n
    (<->) = n -> n -> Dot n
    forall n. n -> n -> Dot n
    (-->)

    infixr 9 <->

    -- -----------------------------------------------------------------------------