

Circular Data Structures in Haskell - dpatru
http://haskell.org/wikisnapshot/TyingTheKnot.html

======
dpatru
It took me a while to understand how he built the doubly linked list. Here's
my explanation.

You want to build a function which takes two doubly linked lists (DLList) and
some values and inserts the values in between the lists and returns the
starting and ending nodes of the new DDList. Call the function go.

    
    
      go leftDLList values rightDLList -> (start, stop)
    

Now start and stop will end up being the original boundaries: RightDLList will
be the DLList node which contains the first inserted element, and leftDLList
will contain the last inserted element. Thus when we run out of elements to
insert, just return the starting and stopping nodes. In Haskell:

go startingN [] stoppingN = (stoppingN, startingN)

If we haven't run out of values, then we simply build a new DLList node for
the first value, and recurse with the new node as the first node.

    
    
      go prev (x:xs) next = (this, last)
        where this = DLNode prev x rest
              (rest, last) = go this xs next
    

That's it! now we just call go with starting and ending nodes which we haven't
defined.

    
    
      (first, last) = go last (x:xs) first
    
    

Because Haskell is lazy, it doesn't try to evaluate last and first until it
needs to. The recursive call to go will bind first to (DLNode last x rest).
Last will be bound when the base case definition of go is called. By that time
go is called with a real DLNode as it's first argument.

