In shang’s answer you can see how to represent a graph using laziness. The problem with these representations is that they are very difficult to change. The knot-tying trick is useful only if you’re going to build a graph once, and afterward it never changes.
In practice, should I actually want to do something with my graph, I use the more pedestrian representations:
- Edge list
- Adjacency list
- Give a unique label to each node, use the label instead of a pointer, and keep a finite map from labels to nodes
If you’re going to be changing or editing the graph frequently, I recommend using a representation based on Huet’s zipper. This is the representation used internally in GHC for control-flow graphs. You can read about it here: