haskell / fgl

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

gfiltermap shows unexpected behaviour #55

Closed norm2782 closed 7 years ago

norm2782 commented 8 years ago

The gfiltermap function shows unexpected (for me, at least) behaviour. Its description: "Build a graph out of the contexts for which the predicate is true.", where context is represented by type Context, which is documented as follows: "Links to the Node, the Node itself, a label, links from the Node."

Given these descriptions, I would expect that for every node I get its predecessors and successors in the context. This does not appear the case in the example below:

{-# LANGUAGE TupleSections #-}

module Test where

import Debug.Trace
import Data.Graph.Inductive

main :: IO ()
main = prettyPrint test

test :: Gr () ()
test = gfiltermap filterGraph testGraph
  where
  filterGraph = Just . traceShowId
{-
 - 1 <-4<-- 2
 - /\    -/|
 -  \    /
 -   \3\/_
 -}
  testGraph = mkGraph testNodes testEdges
    where
    testNodes = map (,()) [1, 2, 3, 4]
    testEdges = [ (2, 4, ())
                , (4, 1, ())
                , (2, 3, ())
                , (3, 1, ())
                , (3, 2, ())
                ]

Executing main gives the following output, where the first four lines are the output from traceShowId and the last four lines the output of prettyPrint:

([((),3),((),4)],1,(),[])
([((),3)],2,(),[((),3),((),4)])
([],3,(),[])
([],4,(),[])

1:()->[]
2:()->[((),3),((),4)]
3:()->[((),1),((),2)]
4:()->[((),1)]

While the code faithfully reconstructs the original graph (as is also tested in the test suite), the trace output shows some strange behaviour. For example, I would expect node 4 to have node 1 and node 2 in its context, but its context is empty.

So, either gfiltermap has a bug, in which case it would be great if that could be fixed. Or gfiltermap's documentation should possibly be updated to reflect gfiltermap's current behaviour.

I am using revision 71b66d6.

ivan-m commented 8 years ago

I thought I had responded to this but turns out I hadn't :/

gfiltermap works by recursively calling match on the graph, and this is the behaviour it has always had.

As such, this may be a documentation issue (it's come up before).