diff --git a/comfort-graph.cabal b/comfort-graph.cabal
--- a/comfort-graph.cabal
+++ b/comfort-graph.cabal
@@ -1,5 +1,5 @@
 Name:                comfort-graph
-Version:             0.0.3.3
+Version:             0.0.4
 Synopsis:            Graph structure with type parameters for nodes and edges
 Description:
   This graph structure is based on "Data.Map"
@@ -36,6 +36,7 @@
   For examples see the @linear-circuit@ package and its tests.
   The @ResistorCube@ test demonstrates non-integer node types
   and the @Tree@ test demonstrates multigraphs.
+  Another application is @cabal-sort@.
   .
   Currently the package does not contain any advanced algorithm,
   just the data structure and some manipulation functions.
@@ -59,7 +60,7 @@
   Makefile
 
 Source-Repository this
-  Tag:         0.0.3.3
+  Tag:         0.0.4
   Type:        darcs
   Location:    https://hub.darcs.net/thielema/comfort-graph
 
@@ -96,6 +97,7 @@
     Test.Data.Graph.Comfort
   Build-Depends:
     comfort-graph,
+    doctest-lib >=0.1 && <0.2,
     doctest-exitcode-stdio >=0.0 && <0.1,
     QuickCheck >=2 && <3,
     transformers,
diff --git a/src/Data/Graph/Comfort.hs b/src/Data/Graph/Comfort.hs
--- a/src/Data/Graph/Comfort.hs
+++ b/src/Data/Graph/Comfort.hs
@@ -23,7 +23,11 @@
    adjacentEdgeSet, adjacentEdges,
    isLoop,
    pathExists,
+   depthFirstSearch,
+   topologicalSort,
+   components,
    isConsistent,
+   stronglyConnectedComponents,
 
    -- * Manipulate labels
    mapNode, mapNodeWithKey,
@@ -52,19 +56,22 @@
 import qualified Data.Graph.Comfort.Map as MapU
 import qualified Data.Graph.Comfort.TotalMap as TMap
 
+import qualified Control.Monad.Trans.State as MS
 import Control.Monad.Trans.Identity (IdentityT(IdentityT, runIdentityT))
+import Control.Monad (liftM2, when, (=<<))
+import Control.Applicative (Applicative, liftA2, liftA3, pure)
 import Data.Functor.Classes
          (Eq1(liftEq), Ord1(liftCompare), Show1(liftShowsPrec))
 
-import qualified Data.Set as Set
 import qualified Data.Map as Map
+import qualified Data.Set as Set
+import qualified Data.Tree as Tree
 import qualified Data.Traversable as Trav
 import qualified Data.Foldable as Fold
-import Control.Monad (liftM2, (=<<))
-import Control.Applicative (Applicative, liftA2, liftA3)
 import Data.Foldable (Foldable, foldMap)
-import Data.Set (Set)
 import Data.Map (Map)
+import Data.Set (Set)
+import Data.Tree (Tree, Forest)
 import Data.Monoid
          (Monoid, mempty, mappend, All(All), getAll, Endo(Endo), appEndo)
 import Data.Semigroup (Semigroup((<>)), )
@@ -72,10 +79,11 @@
 
 import qualified Test.QuickCheck as QC
 
+import qualified Data.List as List
 import Data.Functor (Functor, fmap)
 import Data.List (map, any, all, (++))
 import Data.String (String)
-import Data.Maybe (Maybe)
+import Data.Maybe (Maybe(Nothing, Just), catMaybes)
 import Data.Bool (Bool(False), not, (&&), (||))
 import Data.Eq (Eq, (==))
 import Data.Ord (Ord, Ordering(LT,GT), (<), (>))
@@ -95,6 +103,8 @@
 >>> import qualified Data.Map as Map
 >>> import qualified Data.Set as Set
 >>> import qualified Data.Char as Char
+>>> import Data.Graph.Comfort (Graph, DirEdge(DirEdge), UndirEdge(UndirEdge))
+>>> import Data.Tuple.HT (mapSnd)
 >>>
 >>> import qualified Control.Monad.Trans.Class as MT
 >>> import qualified Control.Monad.Trans.State as MS
@@ -129,6 +139,32 @@
 >>> evalTraverse nl el =
 >>>    flip MS.evalState el . flip MS.evalStateT nl .
 >>>    Graph.traverse nodeAction (MT.lift . edgeAction)
+>>>
+>>>
+>>> (*-*) :: n -> n -> UndirEdge n
+>>> (*-*) = UndirEdge
+>>>
+>>> (*->) :: n -> n -> DirEdge n
+>>> (*->) = DirEdge
+>>>
+>>> unlabGraph ::
+>>>    (Graph.Edge edge, Ord (edge node), Ord node) =>
+>>>    [node] -> [edge node] -> Graph edge node () ()
+>>> unlabGraph ns es =
+>>>    let label = map (flip (,) ()) in
+>>>    Graph.fromMap
+>>>       (Map.fromList $ label $ ns ++ map Graph.from es ++ map Graph.to es)
+>>>       (Map.fromList $ label es)
+>>>
+>>> addReversedEdges ::
+>>>    (Ord node) => Graph DirEdge node el nl -> Graph DirEdge node el nl
+>>> addReversedEdges gr =
+>>>    Graph.fromMap
+>>>       (Graph.nodeLabels gr)
+>>>       (Map.union
+>>>         (Graph.edgeLabels gr)
+>>>         (Map.mapKeys (\(Graph.DirEdge f t) -> Graph.DirEdge t f) $
+>>>            Graph.edgeLabels gr))
 -}
 
 {-
@@ -217,6 +253,20 @@
 data DirEdge node = DirEdge node node
    deriving (Eq, Ord, Show)
 
+{- |
+Danger:
+Do not use the data constructor 'UndirEdge'
+because it does not ensure ordering of members.
+Use the smart constructor 'undirEdge' instead.
+
+'UndirEdge' is not really an undirected edge.
+It is more like a directed edge with a canonical direction.
+Working with 'UndirEdge' requires caution.
+In @Graph UndirEdge@ 'predecessors' are all edges to lower nodes
+with respect to @Ord node@,
+whereas 'successors' are all edges to higher nodes.
+Thus you get all connection only when merging 'predecessors' and 'successors'.
+-}
 data UndirEdge node = UndirEdge node node
    deriving (Eq, Ord, Show)
 
@@ -485,9 +535,14 @@
 lookupNode :: (Ord n) => n -> Graph e n el nl -> Maybe nl
 lookupNode n (Graph g) = fmap snd3 $ Map.lookup n g
 
+memberNode :: (Ord n) => n -> Graph e n el nl -> Bool
+memberNode n (Graph g) = Map.member n g
+
 {- |
 Direct predecessors of a node,
 i.e. nodes with an outgoing edge to the queried node.
+
+It is a checked error, if the queried node is not contained in the graph.
 -}
 predecessors :: (Edge e, Ord n) => Graph e n el nl -> n -> [n]
 predecessors g n =
@@ -497,6 +552,8 @@
 {- |
 Direct successors of a node,
 i.e. nodes with an incoming edge from the queried node.
+
+It is a checked error, if the queried node is not contained in the graph.
 -}
 successors :: (Edge e, Ord n) => Graph e n el nl -> n -> [n]
 successors g n =
@@ -800,6 +857,124 @@
           not (isEmpty gr) &&
           (a==dst || (any (go (deleteNode a gr)) $ successors gr a))
    in  flip go src
+
+depthFirstSearch ::
+   (Edge edge, Ord node) =>
+   Graph edge node edgeLabel nodeLabel -> Forest node
+depthFirstSearch =
+   let go = do
+         gr <- MS.get
+         case nodes gr of
+            n:_ -> liftA2 (:) (depthFirstSearchFrom n) go
+            [] -> pure []
+   in MS.evalState go
+
+depthFirstSearchFrom ::
+   (Edge edge, Ord node) =>
+   node -> MS.State (Graph edge node edgeLabel nodeLabel) (Tree node)
+depthFirstSearchFrom n = do
+   gr <- MS.get
+   MS.put $ deleteNode n gr
+   fmap (Tree.Node n . catMaybes) $ Trav.for (successors gr n) $ \succ -> do
+      unvisited <- MS.gets $ memberNode n
+      if unvisited
+         then fmap Just $ depthFirstSearchFrom succ
+         else pure Nothing
+
+{- |
+>>> mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['a'*->'a']
+("","a")
+>>> mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['a'*->'h', 'a'*->'p', 'g'*->'r', 'p'*->'h', 'r'*->'a']
+("graph","")
+>>> mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['h'*->'a', 'a'*->'p', 'g'*->'r', 'p'*->'h', 'r'*->'a']
+("gr","ahp")
+-}
+topologicalSort ::
+   (Edge edge, Ord node) =>
+   Graph edge node edgeLabel nodeLabel ->
+   ([node], Graph edge node edgeLabel nodeLabel)
+topologicalSort gr =
+   let go gr0 startNodes =
+         case Set.minView startNodes of
+            Nothing -> ([], gr0)
+            Just (n,ns) ->
+               let gr1 = deleteNode n gr0 in
+               mapFst (n :) $
+               go gr1 $
+                  Set.filter
+                     (List.null . predecessors gr1)
+                     (Set.fromList $ successors gr0 n)
+                  `Set.union`
+                  ns
+   in go gr . Map.keysSet . Map.filter (Set.null . fst3) . nodeEdges $ gr
+
+{- |
+>>> map Graph.nodes $ Graph.components $ unlabGraph ['d'] ['a'*->'p', 'g'*->'r', 'p'*->'h']
+["ahp","d","gr"]
+>>> map Graph.nodes $ Graph.components $ unlabGraph ['d'] ['a'*-*'p', 'g'*-*'r', 'p'*-*'h']
+["ahp","d","gr"]
+-}
+components ::
+   (Edge edge, Ord node) =>
+   Graph edge node edgeLabel nodeLabel ->
+   [Graph edge node edgeLabel nodeLabel]
+components =
+   let go gr0 =
+         case nodes gr0 of
+            [] -> []
+            n:_ ->
+               let (comp, remaining) = fetchComponent gr0 n in
+               comp : go remaining
+   in go
+
+fetchComponent ::
+   (Edge edge, Ord node) =>
+   Graph edge node edgeLabel nodeLabel -> node ->
+   (Graph edge node edgeLabel nodeLabel,
+    Graph edge node edgeLabel nodeLabel)
+fetchComponent (Graph gr) n =
+   let go comp0 gr0 set =
+         if Set.null set
+            then (Graph comp0, Graph gr0)
+            else
+               let zone = Map.restrictKeys gr0 set
+                   remaining = Map.withoutKeys gr0 set
+                   comp1 = Map.union comp0 zone
+                   newSet =
+                     Set.fromList $
+                        foldMap (map fromWrap . Map.keys . fst3) zone
+                        ++
+                        foldMap (map toWrap . Map.keys . thd3) zone
+               in go comp1 remaining newSet
+   in go Map.empty gr (Set.singleton n)
+
+
+buildReverseQueue :: Tree node -> [node] -> [node]
+buildReverseQueue (Tree.Node n ns) queue =
+   n : List.foldl (flip buildReverseQueue) queue ns
+
+{- |
+>>> map Set.toAscList $ Graph.stronglyConnectedComponents $ unlabGraph ['d'] ['g'*->'r', 'r'*->'a', 'a'*->'g', 'a'*->'p', 'p'*->'h', 'h'*->'p']
+["d","hp","agr"]
+
+prop> \(TestGraph gr) -> Set.fromList (map Graph.nodeSet (Graph.components gr)) == Set.fromList (Graph.stronglyConnectedComponents (addReversedEdges gr))
+-}
+stronglyConnectedComponents ::
+   (Ord node) => Graph DirEdge node edgeLabel nodeLabel -> [Set node]
+stronglyConnectedComponents gr =
+   let forest = depthFirstSearch gr
+       queue = List.foldl (flip buildReverseQueue) [] forest
+       assignComponent root n = do
+         assigned <- MS.gets $ Map.member n
+         when (not assigned) $ do
+            MS.modify $ Map.insert n root
+            Fold.mapM_ (assignComponent root) $ predecessors gr n
+       transposeMap =
+         Map.elems . Map.foldl (Map.unionWith Set.union) Map.empty .
+         Map.mapWithKey (\n root -> Map.singleton root $ Set.singleton n)
+   in transposeMap $
+      MS.execState (Fold.mapM_ (\n -> assignComponent n n) queue) Map.empty
+
 
 
 -- * Wrap utilities
diff --git a/test/Test/Data/Graph/Comfort.hs b/test/Test/Data/Graph/Comfort.hs
--- a/test/Test/Data/Graph/Comfort.hs
+++ b/test/Test/Data/Graph/Comfort.hs
@@ -1,17 +1,20 @@
 -- Do not edit! Automatically created with doctest-extract from src/Data/Graph/Comfort.hs
-{-# LINE 91 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 99 "src/Data/Graph/Comfort.hs" #-}
 
 module Test.Data.Graph.Comfort where
 
+import Test.DocTest.Base
 import qualified Test.DocTest.Driver as DocTest
 
-{-# LINE 92 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 100 "src/Data/Graph/Comfort.hs" #-}
 import     Test.Base
 
 import     qualified Data.Graph.Comfort as Graph
 import     qualified Data.Map as Map
 import     qualified Data.Set as Set
 import     qualified Data.Char as Char
+import     Data.Graph.Comfort (Graph, DirEdge(DirEdge), UndirEdge(UndirEdge))
+import     Data.Tuple.HT (mapSnd)
 
 import     qualified Control.Monad.Trans.Class as MT
 import     qualified Control.Monad.Trans.State as MS
@@ -47,150 +50,217 @@
        flip MS.evalState el . flip MS.evalStateT nl .
        Graph.traverse nodeAction (MT.lift . edgeAction)
 
+
+(*-*)     :: n -> n -> UndirEdge n
+(*-*)     = UndirEdge
+
+(*->)     :: n -> n -> DirEdge n
+(*->)     = DirEdge
+
+unlabGraph     ::
+       (Graph.Edge edge, Ord (edge node), Ord node) =>
+       [node] -> [edge node] -> Graph edge node () ()
+unlabGraph     ns es =
+       let label = map (flip (,) ()) in
+       Graph.fromMap
+          (Map.fromList $ label $ ns ++ map Graph.from es ++ map Graph.to es)
+          (Map.fromList $ label es)
+
+addReversedEdges     ::
+       (Ord node) => Graph DirEdge node el nl -> Graph DirEdge node el nl
+addReversedEdges     gr =
+       Graph.fromMap
+          (Graph.nodeLabels gr)
+          (Map.union
+            (Graph.edgeLabels gr)
+            (Map.mapKeys (\(Graph.DirEdge f t) -> Graph.DirEdge t f) $
+               Graph.edgeLabels gr))
+
 test :: DocTest.T ()
 test = do
- DocTest.printPrefix "Data.Graph.Comfort:358: "
-{-# LINE 358 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:408: "
+{-# LINE 408 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 358 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 408 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) -> Graph.isConsistent (Graph.reverse gr))
- DocTest.printPrefix "Data.Graph.Comfort:359: "
-{-# LINE 359 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:409: "
+{-# LINE 409 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 359 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 409 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) -> Graph.reverse (Graph.reverse gr) == gr)
- DocTest.printPrefix "Data.Graph.Comfort:410: "
-{-# LINE 410 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:460: "
+{-# LINE 460 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 410 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 460 "src/Data/Graph/Comfort.hs" #-}
      (Graph.isEmpty (Graph.empty :: MonoGraph))
- DocTest.printPrefix "Data.Graph.Comfort:411: "
-{-# LINE 411 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:461: "
+{-# LINE 461 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 411 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 461 "src/Data/Graph/Comfort.hs" #-}
      (Graph.isConsistent (Graph.empty :: MonoGraph))
- DocTest.printPrefix "Data.Graph.Comfort:465: "
-{-# LINE 465 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:515: "
+{-# LINE 515 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 465 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 515 "src/Data/Graph/Comfort.hs" #-}
      (\(GraphAndEdge gr e) -> Graph.lookupEdge e gr == Map.lookup e (Graph.edgeLabels gr))
- DocTest.printPrefix "Data.Graph.Comfort:483: "
-{-# LINE 483 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:533: "
+{-# LINE 533 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 483 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 533 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) n -> Graph.lookupNode n gr == Map.lookup n (Graph.nodeLabels gr))
- DocTest.printPrefix "Data.Graph.Comfort:527: "
-{-# LINE 527 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:584: "
+{-# LINE 584 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 527 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 584 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) n -> Graph.isConsistent $ deleteNodeIfExists n gr)
- DocTest.printPrefix "Data.Graph.Comfort:528: "
-{-# LINE 528 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:585: "
+{-# LINE 585 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 528 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 585 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) n nl -> Graph.deleteNode n (Graph.insertNode n nl gr) == deleteNodeIfExists n gr)
- DocTest.printPrefix "Data.Graph.Comfort:529: "
-{-# LINE 529 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:586: "
+{-# LINE 586 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 529 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 586 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) -> let isolatedNodes = filter (isolated gr) $ Graph.nodes gr in not (null isolatedNodes) ==> QC.forAll (QC.elements isolatedNodes) $ \n nl -> Graph.insertNode n nl gr == Graph.insertNode n nl (Graph.deleteNode n gr))
- DocTest.printPrefix "Data.Graph.Comfort:555: "
-{-# LINE 555 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:612: "
+{-# LINE 612 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 555 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 612 "src/Data/Graph/Comfort.hs" #-}
      (\(GraphAndEdge gr e) -> Graph.isConsistent $ Graph.deleteEdge e gr)
- DocTest.printPrefix "Data.Graph.Comfort:556: "
-{-# LINE 556 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:613: "
+{-# LINE 613 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 556 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 613 "src/Data/Graph/Comfort.hs" #-}
      (\(GraphAndEdge gr e) el -> Graph.deleteEdge e (Graph.insertEdge e el gr) == Graph.deleteEdge e gr)
- DocTest.printPrefix "Data.Graph.Comfort:557: "
-{-# LINE 557 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:614: "
+{-# LINE 614 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 557 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 614 "src/Data/Graph/Comfort.hs" #-}
      (\(GraphAndEdge gr e) el -> Graph.insertEdge e el gr == Graph.insertEdge e el (Graph.deleteEdge e gr))
- DocTest.printPrefix "Data.Graph.Comfort:568: "
-{-# LINE 568 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:625: "
+{-# LINE 625 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 568 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 625 "src/Data/Graph/Comfort.hs" #-}
      (\(GraphAndEdge gr e) -> Graph.filterEdgeWithKey (\ei _ -> e/=ei) gr == Graph.deleteEdge e gr)
- DocTest.printPrefix "Data.Graph.Comfort:621: "
-{-# LINE 621 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:678: "
+{-# LINE 678 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 621 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 678 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) n nl -> Graph.isConsistent $ Graph.insertNode n nl gr)
- DocTest.printPrefix "Data.Graph.Comfort:622: "
-{-# LINE 622 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:679: "
+{-# LINE 679 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 622 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 679 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) n nl -> Graph.lookupNode n (Graph.insertNode n nl gr) == Just nl)
- DocTest.printPrefix "Data.Graph.Comfort:634: "
-{-# LINE 634 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:691: "
+{-# LINE 691 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 634 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 691 "src/Data/Graph/Comfort.hs" #-}
      (\(GraphAndEdge gr e) el -> Graph.isConsistent $ Graph.insertEdge e el gr)
- DocTest.printPrefix "Data.Graph.Comfort:635: "
-{-# LINE 635 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:692: "
+{-# LINE 692 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 635 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 692 "src/Data/Graph/Comfort.hs" #-}
      (\(GraphAndEdge gr e) el -> Graph.lookupEdge e (Graph.insertEdge e el gr) == Just el)
- DocTest.printPrefix "Data.Graph.Comfort:669: "
-{-# LINE 669 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:726: "
+{-# LINE 726 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 669 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 726 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) -> gr == Graph.fromMap (Graph.nodeLabels gr) (Graph.edgeLabels gr))
- DocTest.printPrefix "Data.Graph.Comfort:689: "
-{-# LINE 689 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:746: "
+{-# LINE 746 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 689 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 746 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) -> Graph.mapNode id gr == gr)
- DocTest.printPrefix "Data.Graph.Comfort:702: "
-{-# LINE 702 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:759: "
+{-# LINE 759 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 702 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 759 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) -> Graph.mapEdge id gr == gr)
- DocTest.printPrefix "Data.Graph.Comfort:738: "
-{-# LINE 738 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:795: "
+{-# LINE 795 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 738 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 795 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) nl -> Graph.isConsistent $ evalTraverseNode nl gr)
- DocTest.printPrefix "Data.Graph.Comfort:739: "
-{-# LINE 739 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:796: "
+{-# LINE 796 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 739 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 796 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) -> runIdentity (Graph.traverseNode (Identity . Char.toUpper) gr) == Graph.mapNode Char.toUpper gr)
- DocTest.printPrefix "Data.Graph.Comfort:752: "
-{-# LINE 752 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:809: "
+{-# LINE 809 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 752 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 809 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) el -> Graph.isConsistent $ evalTraverseEdge el gr)
- DocTest.printPrefix "Data.Graph.Comfort:753: "
-{-# LINE 753 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:810: "
+{-# LINE 810 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 753 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 810 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) el -> runIdentity (Graph.traverseEdge (Identity . (el+)) gr) == Graph.mapEdge (el+) gr)
- DocTest.printPrefix "Data.Graph.Comfort:764: "
-{-# LINE 764 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:821: "
+{-# LINE 821 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 764 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 821 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) nl el -> Graph.isConsistent $ evalTraverse nl el gr)
- DocTest.printPrefix "Data.Graph.Comfort:765: "
-{-# LINE 765 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:822: "
+{-# LINE 822 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 765 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 822 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) nl el -> evalTraverse nl el gr == evalTraverseNode nl (evalTraverseEdge el gr))
- DocTest.printPrefix "Data.Graph.Comfort:766: "
-{-# LINE 766 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:823: "
+{-# LINE 823 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 766 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 823 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) nl el -> evalTraverse nl el gr == evalTraverseEdge el (evalTraverseNode nl gr))
- DocTest.printPrefix "Data.Graph.Comfort:767: "
-{-# LINE 767 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:824: "
+{-# LINE 824 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 767 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 824 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) nl -> flip MS.evalState nl (Graph.traverseNode nodeAction gr) == flip MS.evalState nl (Graph.traverse nodeAction pure gr))
- DocTest.printPrefix "Data.Graph.Comfort:768: "
-{-# LINE 768 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:825: "
+{-# LINE 825 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property
-{-# LINE 768 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 825 "src/Data/Graph/Comfort.hs" #-}
      (\(TestGraph gr) el -> flip MS.evalState el (Graph.traverseEdge edgeAction gr) == flip MS.evalState el (Graph.traverse pure edgeAction gr))
+ DocTest.printPrefix "Data.Graph.Comfort:885: "
+{-# LINE 885 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.example
+{-# LINE 885 "src/Data/Graph/Comfort.hs" #-}
+   (mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['a'*->'a'])
+  [ExpectedLine [LineChunk "(\"\",\"a\")"]]
+ DocTest.printPrefix "Data.Graph.Comfort:887: "
+{-# LINE 887 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.example
+{-# LINE 887 "src/Data/Graph/Comfort.hs" #-}
+   (mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['a'*->'h', 'a'*->'p', 'g'*->'r', 'p'*->'h', 'r'*->'a'])
+  [ExpectedLine [LineChunk "(\"graph\",\"\")"]]
+ DocTest.printPrefix "Data.Graph.Comfort:889: "
+{-# LINE 889 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.example
+{-# LINE 889 "src/Data/Graph/Comfort.hs" #-}
+   (mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['h'*->'a', 'a'*->'p', 'g'*->'r', 'p'*->'h', 'r'*->'a'])
+  [ExpectedLine [LineChunk "(\"gr\",\"ahp\")"]]
+ DocTest.printPrefix "Data.Graph.Comfort:912: "
+{-# LINE 912 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.example
+{-# LINE 912 "src/Data/Graph/Comfort.hs" #-}
+   (map Graph.nodes $ Graph.components $ unlabGraph ['d'] ['a'*->'p', 'g'*->'r', 'p'*->'h'])
+  [ExpectedLine [LineChunk "[\"ahp\",\"d\",\"gr\"]"]]
+ DocTest.printPrefix "Data.Graph.Comfort:914: "
+{-# LINE 914 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.example
+{-# LINE 914 "src/Data/Graph/Comfort.hs" #-}
+   (map Graph.nodes $ Graph.components $ unlabGraph ['d'] ['a'*-*'p', 'g'*-*'r', 'p'*-*'h'])
+  [ExpectedLine [LineChunk "[\"ahp\",\"d\",\"gr\"]"]]
+ DocTest.printPrefix "Data.Graph.Comfort:960: "
+{-# LINE 960 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.property
+{-# LINE 960 "src/Data/Graph/Comfort.hs" #-}
+     (\(TestGraph gr) -> Set.fromList (map Graph.nodeSet (Graph.components gr)) == Set.fromList (Graph.stronglyConnectedComponents (addReversedEdges gr)))
+ DocTest.printPrefix "Data.Graph.Comfort:957: "
+{-# LINE 957 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.example
+{-# LINE 957 "src/Data/Graph/Comfort.hs" #-}
+   (map Set.toAscList $ Graph.stronglyConnectedComponents $ unlabGraph ['d'] ['g'*->'r', 'r'*->'a', 'a'*->'g', 'a'*->'p', 'p'*->'h', 'h'*->'p'])
+  [ExpectedLine [LineChunk "[\"d\",\"hp\",\"agr\"]"]]
