algorithmhaskellgraphgraphvizquotes

How do I correctly draw edge between records with Graphviz and Haskell


I'm trying to generate a flowchart with Haskell and the Graphviz binding. I want to create edge between nodes with records as it is possible to do it : https://graphviz.org/doc/info/shapes.html.

I tried this code snippet :

main = do
  let dia = digraph (Str (T.pack "Test")) $ do
                     graphAttrs [style filled, color LightGray]
                     node "mynode1" [style filled, color Blue,Shape Record, Label (StrLabel (T.pack "{mynode1|<f0> one|<f1> two}") )]
                     node "mynode2" [style filled, color Blue,Shape Record, Label (StrLabel (T.pack "{mynode2|<f0> one|<f1> two}") )]
                     node "mynode3" [style filled, color Blue,Shape Record, Label (StrLabel (T.pack "{mynode3|<f0> one|<f1> two}") )]
                     edge "mynode1:f0"  "mynode3:f1" [color Red,Shape Record]
                     "mynode1:f0" --> "mynode2:f1"
                     "mynode1:f1" --> "mynode2:f1"

  runGraphvizCommand Dot dia Pdf "testDot.pdf"
  runGraphvizCommand Dot dia DotOutput "testDot.dot"

and I get :

enter image description here

And that's not what I want !

When I edit the dot file generated by this program, I see :

digraph Test {
  graph [bb="0,0,654.64,142",
    color=lightgray,
    style=filled
  ];
  node [label="\N"];
  mynode1   [color=blue,
    height=0.97222,
    label="{mynode1|<f0> one|<f1> two}",
    pos="41,107",
    rects="0,118.5,82,141.5 0,95.5,82,118.5 0,72.5,82,95.5",
    shape=record,
    style=filled,
    width=1.1389];
  mynode2   [color=blue,
    height=0.97222,
    label="{mynode2|<f0> one|<f1> two}",
    pos="141,107",
    rects="100,118.5,182,141.5 100,95.5,182,118.5 100,72.5,182,95.5",
    shape=record,
    style=filled,
    width=1.1389];
  mynode3   [color=blue,
    height=0.97222,
    label="{mynode3|<f0> one|<f1> two}",
    pos="241,107",
    rects="200,118.5,282,141.5 200,95.5,282,118.5 200,72.5,282,95.5",
    shape=record,
    style=filled,
    width=1.1389];
  "mynode1:f0"  [height=0.5,
    pos="366,107",
    width=1.8234];
  "mynode3:f1"  [height=0.5,
    pos="291,18",
    width=1.8234];
  "mynode1:f0" -> "mynode3:f1"  [color=red,
    pos="e,305.42,35.723 351.54,89.226 340.33,76.227 324.65,58.03 312.05,43.417",
    shape=record];
  "mynode2:f2"  [height=0.5,
    pos="440,18",
    width=1.8234];
  "mynode1:f0" -> "mynode2:f1"  [pos="e,425.78,35.723 380.27,89.226 391.32,76.227 406.8,58.03 419.23,43.417"];
  "mynode1:f1"  [height=0.5,
    pos="589,107",
    width=1.8234];
  "mynode2:f1"  [height=0.5,
    pos="589,18",
    width=1.8234];
  "mynode1:f1" -> "mynode2:f1"  [pos="e,589,36.153 589,88.812 589,76.657 589,60.114 589,46.182"];
}

I tried to remove the quotes around the nodes names and then I have the correct result :

digraph Test {
  graph [bb="0,0,654.64,142",
    color=lightgray,
    style=filled
  ];
  node [label="\N"];
  mynode1   [color=blue,
    height=0.97222,
    label="{mynode1|<f0> one|<f1> two}",
    pos="41,107",
    rects="0,118.5,82,141.5 0,95.5,82,118.5 0,72.5,82,95.5",
    shape=record,
    style=filled,
    width=1.1389];
  mynode2   [color=blue,
    height=0.97222,
    label="{mynode2|<f0> one|<f1> two}",
    pos="141,107",
    rects="100,118.5,182,141.5 100,95.5,182,118.5 100,72.5,182,95.5",
    shape=record,
    style=filled,
    width=1.1389];
  mynode3   [color=blue,
    height=0.97222,
    label="{mynode3|<f0> one|<f1> two}",
    pos="241,107",
    rects="200,118.5,282,141.5 200,95.5,282,118.5 200,72.5,282,95.5",
    shape=record,
    style=filled,
    width=1.1389];
  mynode1:f0    [height=0.5,
    pos="366,107",
    width=1.8234];
  mynode3:f1    [height=0.5,
    pos="291,18",
    width=1.8234];
  mynode1:f0 -> mynode3:f1  [color=red,
    pos="e,305.42,35.723 351.54,89.226 340.33,76.227 324.65,58.03 312.05,43.417",
    shape=record];
  mynode2:f2    [height=0.5,
    pos="440,18",
    width=1.8234];
  mynode1:f0 -> mynode2:f1  [pos="e,425.78,35.723 380.27,89.226 391.32,76.227 406.8,58.03 419.23,43.417"];
  mynode1:f1    [height=0.5,
    pos="589,107",
    width=1.8234];
  mynode2:f1    [height=0.5,
    pos="589,18",
    width=1.8234];
  mynode1:f1 -> mynode2:f1  [pos="e,589,36.153 589,88.812 589,76.657 589,60.114 589,46.182"];
}

enter image description here

Is it possible to render Dot code without quotes with the Haskell Graphviz binding ?

Does an option exist to correctly render edge between records with Haskell and Graphviz ?


Solution

  • You can use edge to specify record labels for the head and tail with the constructors HeadPort and LabelledPort.

    edge "mynode1" "mynode2"
        [ HeadPort (LabelledPort (PN (T.pack "f0")) Nothing)
        , TailPort (LabelledPort (PN (T.pack "f1")) Nothing)
        ]