This post is about fgl
, the usual Haskell graph library.
Suppose I have a graph and I want to label the leaves, a leaf being a vertex without outgoing edges. I draft the trivial predicate on a context:
isLeaf :: Context a b -> Bool
isLeaf (_, _, _, [ ]) = True
isLeaf (_, _, _, _ ) = False
— And then I draft an equally trivial, if verbose, function to label a context with a predicate.
mark :: (Context a b -> Bool) -> Context a b -> Context (a, Bool) b
mark p x@(edgesIn, identifier, label , edgesOut)
= (edgesIn, identifier, (label, p x), edgesOut)
What could go wrong. And yet.
λ ab
mkGraph [(1,'a'),(2,'b')] [(1,2,()),(2,1,())]
λ gmap (mark isLeaf) ab
mkGraph [(1,('a',False)),(2,('b',True))] [(1,2,()),(2,1,())]
ab
, being a cycle, has no leaves, and yet a node is marked. After a bit of thinking, I understand that this is due exactly to the inductive nature of the function gmap
: when it removes a context from ab
, it modifies the context of the remaining nodes, removing the edges they share with the departed context.
But this is not what I want. It gives me a stack; what I want is a zipper. I want to have my symmetry. I am sure I can hack around this problem, but I wonder if there is a clean, obvious, standard solution.