How to represent mapping between two trees in Haskell? : <p>I'm trying to implement a tree-processing algorithm in Haskell, and (due to the fact this is my first Haskell program!), am struggling with the design of the data structures.  Can any of the FP gurus out there lend a hand?</p>

<p>I'll start by describing the important characteristics of the algorithm, sketch out how I would approach this using an imperative language, and finish with the stumbling baby-steps I have made so far in Haskell.</p>

<h1>The problem</h1>

<p>I won't describe the full algorithm in detail, but the salient points are as follows:</p>

<ul>
<li>The algorithm operates on two rose trees, X and Y.</li>
<li>The first phase of the algorithm computes some derived properties for each node, based on its label and attributes, and those of its descendants.</li>
<li>These derived properties are used to compute a partial mapping between the two trees, such that a node in X may be associated with a node in Y and vice versa.  Because the mapping is partial, any node in X or Y may either be mapped (i.e. have a partner the other tree), or alternatively may be unmapped.</li>
<li>The final phase of the algorithm optimises these mappings, via a sequence of operations which inspect parent / children / siblings of mapped nodes.</li>
</ul>

<p>The data structures must therefore have the following characteristics:</p>

<ul>
<li>Given a reference to a node, provide access the parent of that node, siblings of that node, and children of that node.</li>
<li>Given a node in an input tree, permit <em>annotation</em> of that node with additional information (derived properties, and an optional reference to a node in the other tree).</li>
</ul>

<h1>Sketch of an imperative solution</h1>

<p>If I was to implement this algorithm using an imperative language, the solution would look something like the following.</p>

<p>Let's assume that the starting point is the following definition of the input tree:</p>

<pre><code>struct node {
    // Identifier for this node, unique within the containing tree
    size_t id;

    // Label of this node
    enum label label;

    // Attributes of this node
    // An attribute can be assumed to be a key-value pair
    // Details of the attributes themselves aren't material to this
    // discussion, so the "attribute" type is left opaque
    struct attribute **attributes;
    size_t n_attributes;

    // Pointer to parent of this node
    // NULL iff this node is root
    struct node *parent;

    // Pointer to first child of this node
    // NULL iff this node is leaf
    struct node *child;

    // Double-linked list of siblings of this node
    struct node *prev;
    struct node *next;
};
</code></pre>

<p>The pointers embedded in each node clearly support the up / down / left / right traversals required by the algorithm.</p>

<p>Annotation can be implemented by defining the following structure:</p>

<pre><code>struct algo_node {
    // Pointer to input node which has been wrapped
    struct node *node;

    // Derived properties computed by first phase of the algorithm
    // Details of the properties themselves aren't material to this
    // discussion, so the "derived" type is left opaque
    struct derived props;

    // Pointer to corresponding node in the other tree
    // NULL iff this node is unmatched
    struct node *match;
};
</code></pre>

<p>The first phase of the algorithm constructs an <code>algo_node</code> for each <code>node</code> in each of the input trees.</p>

<p>Mapping from an <code>algo_node</code> to a <code>node</code> is trivial: follow the embedded <code>*node</code> pointer.  Mapping in the other direction can be supported by storing <code>algo_node</code>s in an array, indexed by the <code>id</code> of the input node.</p>

<p>This is of course just one possible implementation.  Many variations are possible, including</p>

<ul>
<li>Abstracting the children linked list behind a <code>list</code> or <code>queue</code> interface, rather than storing three raw pointers</li>
<li>Instead of associating the input tree with the algorithm tree via indices, encode parent / child / sibling relationships directly in <code>struct algo_node</code></li>
</ul>

<h1>Moving to Haskell</h1>

<p>Let's start with the following definition of the input tree:</p>

<pre><code>data Tree = Leaf Label Attributes
          | Node Label Attributes [Tree]
</code></pre>

<p>Augmentation of each node with an id can be achieved as follows:</p>

<pre><code>data AnnotatedTree = Tree Int

addIndex :: Int -&gt; AnnotatedTree -&gt; (AnnotatedTree, Int)

indexedTree = addIndex 0 tree
</code></pre>

<p>Similarly, we can write a function which computes derived properties:</p>

<pre><code>data AnnotatedTree = Tree DerivedProperties

computeDerived :: DerivedProperties -&gt; AnnotatedTree -&gt; (AnnotatedTree, DerivedProperties)

derivedTree = computeDerived DefaultDerived tree
</code></pre>

<p>The above snippets can be adjusted with little work, such that <code>AnnotatedTree</code> contains both the index and the derived properties.</p>

<p>However, I don't know where to begin with representing mappings between the two trees.  Based on some reading, I have some half-baked ideas ...</p>

<ul>
<li>Define <code>AnnotatedTree</code> to contain a path from the root of the other tree to the mapped node - encoded as a list of indices into each successive children list, <code>[Integer]</code>

<ul>
<li>Use a zipper (of which I currently have a fairly loose understanding) to access the mapped node (or its parent / children / siblings) via the path</li>
<li>Or perhaps use a lens (... of which I have an even less clear understanding!) to do the same</li>
</ul></li>
<li>Define <code>AnnotatedTree</code> to contain a reference to the mapped node directly, as a <code>Maybe Tree</code>

<ul>
<li>But then I don't see a way to walk to parent / siblings of the mapped node</li>
</ul></li>
</ul>

<p>... but I could really do with some guidance on which (if any) of these are worth pursuing.</p>

<p>Any help would be much appreciated!</p>
