Breadth First Tree Traversal in Haskell

As my interest in functional languages has grown, I have become increasingly interested in using them to implement algorithms which I can already write with imperative languages.

For example, I was taught to implement (and I assume most other people as well)  a breadth first traversal of a tree using a queue and a loop.  An example using this method can be found at the wikipedia page for a breadth first search.  When I wanted to try implement a breadth first search in Haskell I quickly realized that algorithm wouldn't port over very well.  I thought a bit and was able to come up with this algorithm:

    1: -- My Implementation
    2: breadth :: Tree a -> [a]
    3: breadth nd =  map rootLabel $ nd : (breadth' [nd])
    4:     where             
    5:       breadth' [] = []
    6:       breadth' nds = let cs = foldr ((++).subForest) [] nds in
    7:                      cs ++ breadth' cs

 

The idea was that each call to breadth' takes a list of nodes (which represents of level of the tree) and will concatenate the children of each of those nodes together and recursively call itself again with that list.  This works but its not pretty Haskell.  When choosing Haskell (from what I have learned) it is best if you can avoid explicit recursion and use built in combinators.  After I coded my breadth first traversal function I decided to look into the Haskell standard libraries to see how it is done there.  What I found was a function called levels which returns a list of lists, where each sub-list is a level of the tree.  I slightly modified this to have the same functionality as my breadth function which creates one list of all the nodes in the breadth first order.

This is the resulting code:

    1: -- Haskell Standard Libraray Implementation
    2: br :: Tree a -> [a]
    3: br t = map rootLabel $
    4:        concat $
    5:        takeWhile (not . null) $                
    6:        iterate (concatMap subForest) [t]

 

This is really slick implementation of what I did above.  The algorithm is the same but the way they went about writing it is so much prettier.