[Haskell-cafe] Graph diagram tools?

Ivan Zakharyaschev imz at altlinux.org
Fri Apr 17 15:48:22 UTC 2015


2015-04-17 4:23 UTC+03:00, Ivan Lazar Miljenovic <ivan.miljenovic at gmail.com>:

>> ### Considering dotgen vs graphviz closer
>> But looking into the examples, I see that `dotgen` can use "Haskell
>> ids" to identify created nodes, whereas in graphviz's monad (see the

To bring more clear context for any readers, I put here a short
excerpt from that dotgen example:

>>     refSpec <- src "S"
>>     c1 <- box "S"
>>     refSpec .->. c1

>> example above) one must supply extra strings as the unique ids (by
>> which we refer to the nodes).

Short example:

>>         "start" --> "a0"
>>         node "start" [shape MDiamond]

> I used Strings as an example, as I was directly converting an existing
> piece of Dot code; the original can be found here:
> http://hackage.haskell.org/package/graphviz-2999.17.0.2/docs/Data-GraphViz-Types.html
> But, you can use any type you like for the node identifiers, as long
> as you make them an instance of the PrintDot class.  That's where the
> `n` in the `Dot n` type comes in.

Ok, thanks for the valuable information!

>> I like the first approach more ("Haskell ids").
> I admittedly don't have any ability in graphviz to create new
> identifiers for you.  I could (just add a StateT to the internal
> monadic stack which keeps track of the next unused node identifier)

Since the API is already monadic, adding another monad into the stack
wouldn't impose big difficulties for the users of the API, because they
won't need to restructure the code (as if it were a transition from
some pure functional code into monadic).

> but I think that would _reduce_ the flexibility of being able to use
> your own type (it would either only work for `Dot Int`, or even if you
> could apply a mapping function to use something like `GraphID`, but
> that has a problem if you have a `Double` with the same value - and
> hence same textual representation - as your Int).

I see:
can have distinct values with the same textual representation.

But if we are thinking about automatically creating new IDs, then this
problem can simply be treated in the code for tracking which IDs have
already been used.

There could be two APIs: a "flexible" one with user-supplied IDs, and
an "automatic" API. The "automatic" one is implemented on top of the
"flexible" one.

> The way I see it, graphviz is usually used for converting existing
> Haskell values into Dot code and then processing with dot, neato, etc.

> My preference - and hence overall design with graphviz - is that you
> would generate the graph first, and _then_ convert it to a Dot
> representation en masse.

If the Haskell representation of the graph doesn't already have unique
IDs for the nodes, then such an "automatic" layer would be useful as
an intermediate step in the conversion. So it seems it won't be
useless even in your standard scenarios.


You name flexibility for the user as an advantage of the existing
approach. As for some advantages of the other approach (with using
Haskell ids for the nodes): the compiler could catch more errors.

For example, if I make a typo in an identifier when introducing an
edge, then Haskell compiler would report this as an unknown

Also the compiler would catch name clashes, if you accidentally give
the same id to two different nodes.

A potential disadvantage is then an increased verbosity: first, create
the nodes, then use them for the edges. Meaning three actions instead of
yours single one:

        "a0" --> "a1"

Still, even in the "automatic ids" approach, this can be written
compactly in a single
line in the spirit of:

    bindM2 (-->) (node [textLabel "a0"]) (node [textLabel "a1"])

without explicitly giving Haskell ids to the two nodes.

Perhaps, this is not important stuff, because--as you write--one is
supposed to use Haskell representations of graphs and then convert
them with graphviz... (I might simply not want to learn another
language for representing graphs apart from dot, that's why I'd like
to use the monadic API: because it closely follows the known dot format.)

My last line of code already looks similar to a code constructing a
Haskell representation of a graph.

I'm just writing down my comments concerning the API, not that I'm
confident that I know a definite way to make it better.

Well, after writing this post and thinking it all over while writing,
I tend to come to a conclusion resonating with your opinion stating
that the monadic API turned out not as useful as you used to think:

it seems that while imposing the monadic style onto the programmer, it
doesn't give the advantages a monad could give (like generating unique
ids automatically and catching errors with undefined or clashing ids).
Without this stateful feature, much else can be done purely with
dedicated graph structures.

What do you think about these comments?

As for dotgen: my wishes could be satisfied simply with the dotgen
package, but--as you wrote--it is not safe w.r.t. to quoting/escaping
user supplied values.

Best regards,

More information about the Haskell-Cafe mailing list