No es lo que yo sé. Tienes que escribir una función para atravesar gráficos.
Primero, decida dónde romper la circularidad. En este caso, es trivial: use los nombres de los nodos (suponiendo que sean únicos dentro de un gráfico). Para una estructura más compleja, como un gráfico con nodos y bordes como tipos separados, tendría que decidir si almacenar bordes con nodos, nodos con bordes o mantener los nodos y bordes completamente separados.
A continuación, enumere todos los nodos en el gráfico. En este caso, la forma obvia es atravesar el gráfico que recoge los nodos en un mapa finito (ver Data.Map). A continuación, almacene cada nodo como un nombre seguido de una lista de otros nombres de nodos.
Recuperar el gráfico significa utilizar el patrón "atar el nudo". Lea el gráfico almacenado en una estructura de [(String, [String])]. A continuación, el gráfico original puede ser reconstruido con el siguiente código:
import qualified Data.Map as M
data Node = Node String [Node]
instance Show Node where
show (Node name others) = "Node " ++ show name ++
" " ++ show (map nodeName others)
where nodeName (Node n _) = n
restoreGraph :: [(String, [String])] -> M.Map String Node
restoreGraph pairs = table
where
table = M.fromList $ map makeNode pairs
makeNode (name, others) = (name, Node name $ map findNode others)
findNode str = fromJust $ M.lookup str table
Nota la recursión mutua: mesa de llama makeNode, que llama findNode, que llama a la mesa. Thanks to lazy evaluation this does the Right Thing.
Edit: código ahora probado y ligeramente expandido.