Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most general way to compute the depth of a tree with something like a fold?

Tags:

haskell

tree

fold

What minimal (most general) information is required to compute depth of a Data.Tree? Is instance of a Data.Foldable sufficient?

I initially tried to fold a Tree and got stuck trying to find right Monoid similar to Max. Something tells me that since Monoid (that would compute depth) needs to be associative, it probably cannot be used to express any fold that needs to be aware of the structure (as in 1 + maxChildrenDepth), but I'm not certain.

I wonder what thought process would let me arrive at right abstraction for such cases.

like image 679
sevo Avatar asked Jan 04 '15 19:01

sevo


People also ask

How do you measure the depth of a tree?

The depth of a node in a binary tree is the total number of edges from the root node to the target node. Similarly, the depth of a binary tree is the total number of edges from the root node to the most distant leaf node.

How do you calculate the depth of a node in a tree?

Approach: The problem can be solved based on the following observations: Depth of a node K (of a Binary Tree) = Number of edges in the path connecting the root to the node K = Number of ancestors of K (excluding K itself).

How do you determine the height and depth of a tree?

The depth(or level) of a node is its distance(i.e. no of edges) from tree's root node. The height is number of edges between root node and furthest leaf. height(node) = 1 + max(height(node.

What is the depth of a tree in data structure?

Depth. In a tree, many edges from the root node to the particular node are called the depth of the tree. In the tree, the total number of edges from the root node to the leaf node in the longest path is known as "Depth of Tree". In the tree data structures, the depth of the root node is 0.


2 Answers

I can't say if it's a minimal/most general amount of information. But one general solution is that a given structure

  • is a catamorphism
  • underlying functor of the catamorphism is Foldable so that it's possible to enumerate sub-terms.

Here is sample code using recursion-schemes.

{-# LANGUAGE TypeFamilies, FlexibleContexts #-}

import Data.Functor.Foldable
import Data.Semigroup
import Data.Tree

depth :: (Recursive f, Foldable (Base f)) => f -> Int
depth = cata ((+ 1) . maybe 0 getMax . getOption
              . foldMap (Option . Just . Max))

-- Necessary instances for Tree:

data TreeF a t = NodeF { rootLabel' :: a, subForest :: [t] }

type instance Base (Tree a) = TreeF a

instance Functor (TreeF a) where
    fmap f (NodeF x ts) = NodeF x (map f ts)

instance Foldable (TreeF a) where
    foldMap f (NodeF _ ts) = foldMap f ts

instance Recursive (Tree a) where
    project (Node x ts) = NodeF x ts
like image 102
Petr Avatar answered Nov 09 '22 01:11

Petr


To answer the first question: Data.Foldable is not enough to compute the depth of the tree. The minimum complete definition of Foldable is foldr, which always has the following semantics:

foldr f z = Data.List.foldr f z . toList

In other words, a Foldable instance is fully characterized by how it behaves on a list projection of the input (ie toList), which will throw away the depth information of a tree.

Other ways of verifying this idea involve the fact that Foldable depends on a monoid instance which has to be associative or the fact that the various fold functions see the elements one by one in some particular order with no other information, which necessarily throws out the actual tree structure. (There has to be more than one tree with the same set of elements in the same relative order.)

I'm not sure what the minimal abstraction would be for trees specifically, but I think the core of your question is actually a bit broader: it would be interesting to see what minimum amount of information is needed to compute arbitrary facts about a type with a fold-like function.

To do this, the actual helper function in the fold would have to take a different sort of argument for each sort of data structure. This naturally leads us to catamorphisms, which are generalized folds over different data types.

You can read more about these generalized folds on a different Stack Overflow question: What constitutes a fold for types other than list? (In the interest of disclosure/self-promotion, I wrote one of the answeres there :P.)

like image 20
Tikhon Jelvis Avatar answered Nov 09 '22 01:11

Tikhon Jelvis