dotGraphGroupNodesByLabel :: Maybe Int -> [String] -> DotGraph -> DotGraph
    dotGraphGroupNodesByLabel maybeMaxDepth prefix graph@(DotGraph nvs name nodes edges subGraphs)
        | isNothing maybeMaxDepth || maxDepth > 0 = DotGraph nvs name nonSubNodes edges subGraphs'
        | otherwise = graph
        where
            Just maxDepth = maybeMaxDepth
            nextDepth = maybeMaxDepth >>= return . (+ (-1))

            level = length prefix

            subGraphs' = subGraphs ++ map (uncurry (dotGraphGroupNodesByLabel nextDepth)) newSubgraphs

            newSubgraphs = mapMaybe makeSubgraph groupedNodes

            nonSubNodes = fromMaybe [] $ lookup "" groupedNodes

            makeSubgraph ("", _) = Nothing
            makeSubgraph (label, nodes) = Just (prefix', DotGraph ("cluster_" ++ escGraphName prefixLabel)
                [("label", prefixLabel)] nodes [] [])
                where
                    prefix' = prefix ++ [label]
                    prefixLabel = joinWith "." prefix'

            groupedNodes = groupByName (nthNameElem level . getLabel) nodes

            groupByName f nodes = map cleanUp $ sortAndGroupByElem fst prefices
                where
                    cleanUp (name, elems) = (name, map snd elems)
                    prefices = map (\thing -> (f thing, thing)) nodes

            getLabel node = fromMaybe "" $ liftM snd $ find ((== "label") . fst) $ dotNodeNVs node
dotGraphGroupNodesByLabel :: Maybe Int -> [String] -> DotGraph -> DotGraph
dotGraphGroupNodesByLabel maybeMaxDepth prefix graph@(DotGraph nvs name nodes edges subGraphs)
        | isNothing maybeMaxDepth || maxDepth > 0 = DotGraph nvs name nonSubNodes edges subGraphs'
        | otherwise = graph
        where
            Just maxDepth = maybeMaxDepth
            nextDepth = maybeMaxDepth >>= return . (+ (-1))

            level = length prefix

            subGraphs' = subGraphs ++ map (uncurry (dotGraphGroupNodesByLabel nextDepth)) newSubgraphs

            newSubgraphs = mapMaybe makeSubgraph groupedNodes

            nonSubNodes = fromMaybe [] $ lookup "" groupedNodes

            makeSubgraph ("", _) = Nothing
            makeSubgraph (label, nodes) = Just (prefix', DotGraph ("cluster_" ++ escGraphName prefixLabel)
                [("label", prefixLabel)] nodes [] [])
                where
                    prefix' = prefix ++ [label]
                    prefixLabel = joinWith "." prefix'

            groupedNodes = groupByName (nthNameElem level . getLabel) nodes

            groupByName f nodes = map cleanUp $ sortAndGroupByElem fst prefices
                where
                    cleanUp (name, elems) = (name, map snd elems)
                    prefices = map (\thing -> (f thing, thing)) nodes

            getLabel node = fromMaybe "" $ liftM snd $ find ((== "label") . fst) $ dotNodeNVs node
dotGraphGroupNodesByLabel maybeMaxDepth prefix graph@(DotGraph nvs name nodes edges subGraphs)
        | isNothing maybeMaxDepth || maxDepth > 0 = DotGraph nvs name nonSubNodes edges subGraphs'
        | otherwise = graph
        where
            Just maxDepth = maybeMaxDepth
            nextDepth = maybeMaxDepth >>= return . (+ (-1))

            level = length prefix

            subGraphs' = subGraphs ++ map (uncurry (dotGraphGroupNodesByLabel nextDepth)) newSubgraphs

            newSubgraphs = mapMaybe makeSubgraph groupedNodes

            nonSubNodes = fromMaybe [] $ lookup "" groupedNodes

            makeSubgraph ("", _) = Nothing
            makeSubgraph (label, nodes) = Just (prefix', DotGraph ("cluster_" ++ escGraphName prefixLabel)
                [("label", prefixLabel)] nodes [] [])
                where
                    prefix' = prefix ++ [label]
                    prefixLabel = joinWith "." prefix'

            groupedNodes = groupByName (nthNameElem level . getLabel) nodes

            groupByName f nodes = map cleanUp $ sortAndGroupByElem fst prefices
                where
                    cleanUp (name, elems) = (name, map snd elems)
                    prefices = map (\thing -> (f thing, thing)) nodes

            getLabel node = fromMaybe "" $ liftM snd $ find ((== "label") . fst) $ dotNodeNVs node