[Haskell-cafe] Re: What do _you_ want to see in FGL?
Heinrich Apfelmus
apfelmus at quantentunnel.de
Sat May 15 04:19:25 EDT 2010
Ivan Lazar Miljenovic wrote:
> Heinrich Apfelmus writes:
>> I'd be happy with either one. :) In both cases, I want to specify a
>> custom vertex type.
>
> Except an abstract type isn't a custom vertex type...
>
>> I can either do that directly if the library permits, though I think the
>> solution with associated types is too cumbersome to be useful for my
>> make example.
>
> Why?
I was under the impression that I would have to define a new graph data
type with FilePath as vertex type and make that an instance of Graph
? In that case, it would be much shorter for me to stick with the clumsy
nodeMap = Map.fromList nodes
index k = Map.findIndex k nodeMap
nodes' = map (\(a,b) -> (index a, b)) nodes
edges' = map (\(a,b,c) -> (index a, index b, c)) edges
>> Or I get an abstract Node type and the library provides just the right
>> functions that make it easy to manage a custom vertex type myself. I had
>> hoped that the Data.Graph.Inductive.NodeMap module provides this,
>> which it doesn't.
>
> Not sure I follow what you're saying here; then again, my graph stuff
> has typically been to create the graph and then do stuff to it _as_ a
> graph (and not wanting/needing to get a specific node based upon its
> label, etc.).
In the make example, I didn't need to get a node based on its label
either. But the graph was a graph of FilePaths and I still have to
implement an association between that and Int . (In fact, I don't know
of any graph whose nodes are unique integers conceptually.)
In other words, I have to make sure that every FilePath is mapped to a
unique integer which I can then glue into a graph. This is not hard to
do with a Data.Map and the four lines of code above do exactly that.
However, I still had to think about it and it took me way too long to
come up with these four lines. What I would like to see is that the
*library* has thought about that for me already.
A good way to ensure that the library has thought about that is to make
the Node type abstract. This way, the library has to provide the
functionality to create and manage nodes, which I would otherwise cobble
together on my own by messing with Int .
One possibility is to offer a function
mkGraph :: Ord node => [(node,a)] -> [(node,node,b)]
-> (Gr a b, NodeMap node)
that accepts a custom vertex type, creates all the necessary unique
integers internally and also returns an association between the newly
created Nodes and the custom node in case I want to refer to the
nodes in the graph with the custom type.
The NodeMap type - while implemented as a Data.Map - is abstract as
well and has the primitives
empty :: NodeMap n
insert :: n -> NodeMap n -> NodeMap n
lookup :: n -> NodeMap n -> Maybe Node
lookupNode :: Node -> NodeMap n -> Maybe n
delete :: Node -> NodeMap n -> NodeMap n
This is all you need to manage the association node <-> Node . In
particular, insert creates new Nodes on the fly.
And since the nodes in the graph and the NodeMap will usually come in
pairs, we can as well give the pair a new name:
type Graph node a b = (Gr a b, NodeMap node)
To summarize: an abstract Node type relieves me from thinking about
the association between my conceptual node type and unique identifiers.
I'd be happy with anything along these lines, the interface above is
just a suggestion.
Regards,
Heinrich Apfelmus
--
http://apfelmus.nfshost.com
More information about the Haskell-Cafe
mailing list