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
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.