How do you represent a graph in Haskell?

后端 未结 8 727
星月不相逢
星月不相逢 2020-11-27 09:39

It\'s easy enough to represent a tree or list in haskell using algebraic data types. But how would you go about typographically representing a graph? It seems that you need

8条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-27 10:26

    As Ben mentioned, cyclic data in Haskell is constructed by a mechanism called "tying the knot". In practice, it means that we write mutually recursive declarations using let or where clauses, which works because the mutually recursive parts are lazily evaluated.

    Here's an example graph type:

    import Data.Maybe (fromJust)
    
    data Node a = Node
        { label    :: a
        , adjacent :: [Node a]
        }
    
    data Graph a = Graph [Node a]
    

    As you can see, we use actual Node references instead of indirection. Here's how to implement a function that constructs the graph from a list of label associations.

    mkGraph :: Eq a => [(a, [a])] -> Graph a
    mkGraph links = Graph $ map snd nodeLookupList where
    
        mkNode (lbl, adj) = (lbl, Node lbl $ map lookupNode adj)
    
        nodeLookupList = map mkNode links
    
        lookupNode lbl = fromJust $ lookup lbl nodeLookupList
    

    We take in a list of (nodeLabel, [adjacentLabel]) pairs and construct the actual Node values via an intermediate lookup-list (which does the actual knot-tying). The trick is that nodeLookupList (which has the type [(a, Node a)]) is constructed using mkNode, which in turn refers back to the nodeLookupList to find the adjacent nodes.

提交回复
热议问题