/// <summary>
        /// Add new child given node data
        /// </summary>
        /// <returns></returns>
        public LabelledTreeNode <TN, TE> AddChild(TE edge, TN childData)
        {
            var child = new LabelledTreeNode <TN, TE>(childData);

            Children.Add(new DirectedEdge <TE, TN>(edge, child));

            return(this);
        }
        /// <summary>
        /// Copy the current tree node and descendents into new instance
        /// </summary>
        /// <returns></returns>
        public LabelledTreeNode <TN, TE> Copy()
        {
            var node = new LabelledTreeNode <TN, TE>(Value);

            foreach (var child in Children)
            {
                node.Children.Add(new DirectedEdge <TE, TN>(child.Edge, child.TerminalNode.Copy()));
            }

            return(node);
        }
        /// <summary>
        /// Traverse the tree and perform operations recursively
        /// </summary>
        /// <returns>
        /// A new tree node that is, at every node, the result of the visit.
        /// The stopper decides whether the exploration of a branch should be passed
        /// </returns>
        public LabelledTreeNode <TY, TE> Traverse <TY>(TreeNodeVisitor <TN, TY> nodeVisitor, Func <LabelledTreeNode <TN, TE>, bool> stopCondition = null)
        {
            var node = new LabelledTreeNode <TY, TE>(nodeVisitor(Value));

            if (stopCondition == null)
            {
                stopCondition = d => false;
            }
            foreach (var child in Children)
            {
                if (!stopCondition(child.TerminalNode))
                {
                    node.AddChild(child.Edge, child.TerminalNode.Traverse(nodeVisitor, stopCondition));
                }
            }

            return(node);
        }
 /// <summary>
 /// Add new child given a node
 /// </summary>
 /// <returns></returns>
 public LabelledTreeNode <TN, TE> AddChild(TE edge, LabelledTreeNode <TN, TE> child)
 {
     Children.Add(new DirectedEdge <TE, TN>(edge, child));
     return(this);
 }