Proposal: improve the Data.Tree API
Milan Straka
fox at ucw.cz
Fri Mar 14 08:15:21 UTC 2014
Hi all,
> -----Original message-----
> From: João Cristóvão <jmacristovao at gmail.com>
> Sent: 2 Mar 2014, 16:47
>
> <snip>
>
> Consider proposal 3.0.b Milan's idea of splitting forest functions to a
> different submodule. Milan, could you please elaborate on that? I didn't
> quite get how they would have the same name...
The idea was to provide two modules, Data.Tree and Data.Tree.Forest. The
methods for Forest would be in Data.Tree.Forest. To use the modules, the
users would write
import qualified Data.Tree as Tree
import qualified Data.Tree.Forest as Forest
and then use the methods as
Tree.lookupTree
Tree.filter
and
Forest.filter
The disadvantage is that the Forest type still has to be defined in
Data.Tree (otherwise we have a module dependency cycle), and that some
methods for both Trees and Forests (unfoldTree + unfoldForest, drawTree
+ drawForest) already exist in Tree.
If we provide both version methods in Data.Tree, the question is whether
we should always use *Tree and *Forest to disambiguate the calls
(filterTree, filterForest), or just use Forest (i.e., filter for Tree,
filterForest for Forest). The current API is not consistent (drawTree
+ drawForest, but levels only, which could be easily defined for Forest
too).
The current proposal is also not consistent in this regard --
lookupTree and lookupTreeInForest, versus filterPruneTree and
filterPruneForest.
> <snip>
>
> -- | Size of the (flattened) tree
> size :: Tree a -> Int
> size = getSum . F.foldMap (const $ Sum 1)
>
> -- | Maximum depth of tree
> maxDepth :: Tree a -> Int
>
> -- | Remove all nodes past a certain depth
> prune :: Int -> Tree a -> Tree a
>
> -- | Take the mirror-image of a tree
> mirror :: Tree a -> Tree a
> mirror (Node a ts) = Node a . reverse $ map mirror ts
>
> -- | List of subtrees (including the tree itself), in pre-order.
> subTrees :: Tree a -> [Tree a]
>
> -- | List of subtrees at each level of the tree.
> subTreesByLevel :: Tree a -> [[Tree a]]
>
> -- | Label each node of the tree with its full subtree.
> cojoin :: :: Tree a -> Tree (Tree a)
> cojoin t@(Node _ ts) = Node t (map cojoin ts)
Should we provide Forest variants of all those methods? We do so for
lookup and filter, so I do not see reason why not for those, except for
API growth.
Cheers,
Milan
More information about the Libraries
mailing list