haskell / fgl

A Functional Graph Library for Haskell
http://hackage.haskell.org/package/fgl
Other
184 stars 54 forks source link

gsel ignores edges to nodes #89

Open EsGeh opened 5 years ago

EsGeh commented 5 years ago

Hello!

I tried to use gsel to find "start nodes", i.e. nodes to which have no edges point. However, gsel seems to treat all "Contexts" as if no edges point to the node:

import qualified Data.Graph.Inductive as Gr

-- use gsel to select start nodes:
startNodes :: Gr.Gr n e -> [Gr.Context n e] 
startNodes =
    Gr.gsel $ \x -> case x of
        ([], _node, _, _outEdges) -> True
        _ -> False

-- example graph:
test :: Gr.Gr String ()
test =
    Gr.mkGraph
        (zip [0..] ["a", "b", "c","d"])
        [(0,1,()),(0,2,()),(1,3,()),(2,3,())]

now, in ghci:

$ > Gr.prettyPrint test
0:"a"->[((),1),((),2)]
1:"b"->[((),3)]
2:"c"->[((),3)]
3:"d"->[]
$ > startNodes test
 [([],0,"a",[((),1),((),2)]),([],1,"b",[((),3)]),([],2,"c",[((),3)]),([],3,"d",[])]

(gsel selects all nodes)

expected result: [([],0,"a",[((),1),((),2)])] (only node 0 should be selected)

nstepp commented 3 years ago

The source of this behavior is almost certainly that gsel uses ufold, which in turn uses matchAny. So the contexts received by the predicate are the result of recursive graph decompositions. When node "b" is considered, "a" is probably removed from the graph, and so does not show up in the context.

Most functions involving contexts behave in this manner. I will often do an explicit map (context g) (nodes g) (or similar) to get a list of full contexts if I want different behavior.

It would be good for the documentation to be more explicit about the behavior of functions that use match, since as it is, the documentation for things like gsel is misleading to the point of being incorrect.