{"id":358,"date":"2022-07-16T19:02:27","date_gmt":"2022-07-16T18:02:27","guid":{"rendered":"https:\/\/informedica.nl\/?p=358"},"modified":"2022-07-17T08:55:49","modified_gmt":"2022-07-17T07:55:49","slug":"trees","status":"publish","type":"post","link":"https:\/\/informedica.nl\/?p=358","title":{"rendered":"Trees"},"content":{"rendered":"\n<p>A tree is a very common datastructure. I stumbled upon this subject because of a requirement that is needed for a mathematical solution. This solution needs to keep track of changes that start with a single change but can have multiple effects. Each effect, i.e. change, can result in turn into multiple changes, hence the need of a tree structure.<\/p>\n\n\n<p><!--more--><\/p>\n\n\n<p>First I read the excellent <a rel=\"noreferrer noopener\" href=\"https:\/\/fsharpforfunandprofit.com\/posts\/recursive-types-and-folds-3b\/\" target=\"_blank\">post<\/a> by Scott Wlaschin about trees as a recursive data structure. Then I tried to find some general purpose library dealing with tree types, however, I couldn&#8217;t find one. Only then I turned &#8220;<a href=\"https:\/\/wiki.c2.com\/?RealProgrammer\" target=\"_blank\" rel=\"noreferrer noopener\">Real Programmer<\/a>&#8221; and tried to translate the code form the post to fulfill my requirements. <\/p>\n\n\n\n<p>But first, what is a tree?<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"581\" src=\"https:\/\/informedica.nl\/wp-content\/uploads\/2022\/07\/image.png\" alt=\"\" class=\"wp-image-359\" srcset=\"https:\/\/informedica.nl\/wp-content\/uploads\/2022\/07\/image.png 600w, https:\/\/informedica.nl\/wp-content\/uploads\/2022\/07\/image-300x291.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><figcaption>Tree with root, branches and leaves<\/figcaption><\/figure>\n\n\n\n<p>So, a tree consists of a root with multiple branches and each branch can have multiple leaves. When we consider a root as just a special case of a branch, a tree, in fact, consists of just two types: the branch type and the leave type. In F# we can model this as:<\/p>\n\n\n\n<pre class=\"wp-block-code has-black-color has-text-color\"><code lang=\"fsharp\" class=\"language-fsharp\">\/\/\/ Recursive tree type with tree-like semantics.\n\/\/\/ So the tree can just consist of a leaf or branch\n\/\/\/ or a branch can have multiple subtrees consisting \n\/\/\/ of either leafs or branches.\n\/\/\/ A leaf or branch can but do not nescessarily be of\n\/\/\/ different types.\ntype GeneralTree&lt;'Branch, 'Leaf&gt; =\n    | Empty\n    | Leaf of leaf: 'Leaf\n    | Branch of branch: 'Branch * trees: GeneralTree&lt;'Branch, 'Leaf&gt; seq \n<\/code><\/pre>\n\n\n\n<p>So, a tree can be<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Empty<\/li><li>Just a leave<\/li><li>Just a branch (with an empty sequence of trees)<\/li><li>A branch with one leave (i.e. a sequence with a &#8216;leave tree&#8217;)<\/li><li>A branch with multiple branches\/leaves (i.e. a sequence of trees)<\/li><\/ul>\n\n\n\n<p>Note that it is easy to derive &#8220;special trees&#8221; from this general tree, like:<\/p>\n\n\n\n<pre class=\"wp-block-code has-black-color has-text-color\"><code lang=\"fsharp\" class=\"language-fsharp\">type BinaryTree&lt;'Node&gt; = \n    | Empty\n    | Node of node: 'Node * left: BinaryTree&lt;'Node&gt; * right: BinaryTree&lt;'Node&gt;\n\n\ntype SimpleTree&lt;'Node&gt; = GeneralTree&lt;'Node, 'Node&gt;\n<\/code><\/pre>\n\n\n\n<p>The &#8220;simple tree&#8221; is a direct subtype of the &#8220;general tree&#8221;. The &#8220;binary tree&#8221; needs to be mapped to a &#8220;general tree&#8221;.<\/p>\n\n\n\n<p>But first the code to handle the general tree.<\/p>\n\n\n\n<pre class=\"wp-block-code has-black-color has-text-color\"><code lang=\"fsharp\" class=\"language-fsharp\">[&lt;RequireQualifiedAccess&gt;]\nmodule GeneralTree =\n\n\n    \/\/\/ Catamorphism of a tree, using:\n    \/\/\/ - fLeaf: that handles a leaf type and\n    \/\/\/ - fBranch: that handles a branch type and\n    \/\/\/ the recursed results of handling the subtrees.\n    let cata fLeaf fBranch (tree: GeneralTree&lt;_, _&gt;) =\n        let rec loop fLeaf fbranch tree =\n            let recurse = loop fLeaf fbranch\n\n            match tree with\n            | Empty -&gt; Empty\n            | Leaf leaf -&gt; leaf |&gt; fLeaf\n            | Branch (branch, subTrees) -&gt;\n                subTrees |&gt; Seq.map recurse |&gt; fbranch branch\n\n        loop fLeaf fBranch tree\n\n\n    \/\/\/ A fold over a tree, using\n    \/\/\/ - fLeaf: that handles a leaf type and the accumulator\n    \/\/\/ - fBranch: that handles a branch type and the accumulator\n    let fold fLeaf fBranch acc (tree: GeneralTree&lt;_, _&gt;) =\n        let rec loop fLeaf fbranch acc tree =\n            let recurse = loop fLeaf fbranch\n\n            match tree with\n            | Empty -&gt; acc\n            | Leaf leaf -&gt; leaf |&gt; fLeaf acc\n            | Branch (branch, subTrees) -&gt;\n                let acc = branch |&gt; fbranch acc\n                subTrees |&gt; Seq.fold recurse acc\n\n        loop fLeaf fBranch acc tree\n\n\n    \/\/\/ Foldback of a tree, using:\n    \/\/\/ - fLeaf: that handles a leaf type and the accumulator\n    \/\/\/ - fBranch: that handles a branch type and the accumulator\n    let foldBack fLeaf fBranch (tree: GeneralTree&lt;_, _&gt;) acc =\n        let rec loop fLeaf fbranch tree fAcc =\n            let recurse = loop fLeaf fbranch\n\n            match tree with\n            | Empty -&gt; fAcc\n            | Leaf leaf -&gt; fun _ -&gt; leaf |&gt; fLeaf (fAcc ())\n            | Branch (branch, subTrees) -&gt;\n                fun _ -&gt; branch |&gt; fBranch (fAcc ())\n                |&gt; Seq.foldBack recurse subTrees\n\n        loop fLeaf fBranch tree (fun () -&gt; acc)\n        |&gt; fun f -&gt; f ()\n\n\n    \/\/\/ Map the leaf and branch types of a tree, using\n    \/\/\/ - fLeaf: to map the leaf type from a -&gt; b and\n    \/\/\/ - fBranch: to map a branch from c -&gt; d\n    let map fLeaf fBranch (tree: GeneralTree&lt;_, _&gt;) =\n        let rec loop fLeaf fBranch tree =\n            let recurse = loop fLeaf fBranch\n\n            match tree with\n            | Empty -&gt; Empty\n            | Leaf leaf -&gt; leaf |&gt; fLeaf |&gt; Leaf\n            | Branch (branch, subTrees) -&gt;\n                (branch |&gt; fBranch, subTrees |&gt; Seq.map recurse)\n                |&gt; Branch\n\n        loop fLeaf fBranch tree\n\n\n    \/\/\/ Iterate through a tree, using\n    \/\/\/ - fLeaf: to handle the leaf type and\n    \/\/\/ - fBranch: to handle the branch type\n    let iter fLeaf fBranch (tree: GeneralTree&lt;_, _&gt;) =\n        let rec loop fLeaf fBranch tree =\n            let recurse = loop fLeaf fBranch\n\n            match tree with\n            | Empty -&gt; ()\n            | Leaf leaf -&gt; leaf |&gt; fLeaf\n            | Branch (branch, trees) -&gt;\n                trees |&gt; Seq.iter recurse\n                branch |&gt; fBranch\n\n        loop fLeaf fBranch tree\n\n\n    \/\/\/ Map the leaf and branch types of a tree, using\n    \/\/\/ - fLeaf: to map the leaf type from a -&gt; b and\n    \/\/\/ - fBranch: to map a branch from c -&gt; d\n    \/\/\/ the map functions also get all the tree indexes:\n    \/\/\/ - p: a sequence of parent indexes\n    \/\/\/ - d: the depth of the tree item\n    \/\/\/ - i: the item number in the parent\n    let mapi fLeaf fBranch (tree: GeneralTree&lt;_, _&gt;) =\n        let rec loop fLeaf fBranch p d i tree =\n            let recurse = loop fLeaf fBranch\n\n            match tree with\n            | Empty -&gt; Empty\n            | Leaf leaf -&gt; leaf |&gt; fLeaf p d i |&gt; Leaf\n            | Branch (branch, subTrees) -&gt;\n                let branch = branch |&gt; fBranch p d i\n                let p = [ i ] |&gt; List.append p\n                let d = d + 1\n\n                (branch,\n                 subTrees\n                 |&gt; Seq.mapi (fun i t -&gt; i, t)\n                 |&gt; Seq.map (fun (i, tree) -&gt; recurse p d i tree))\n                |&gt; Branch\n\n        loop fLeaf fBranch [] 0 0 tree\n\n\n    \/\/\/ Gives an nice string representation of a tree\n    \/\/\/ incorperating all tree specific indexes like:\n    \/\/\/ - parent indexes\n    \/\/\/ - depth (by indentation)\n    \/\/\/ - breath (the count) and\n    \/\/\/ - the item number in the list of the parent\n    let toString leafToString branchToString (tree: GeneralTree&lt;_, _&gt;) =\n        let fLeaf p d i leaf =\n            let leaf = leaf |&gt; leafToString\n            let p = p @ [ i ] |&gt; List.map string |&gt; String.concat \".\"\n            let s = $\"{p} %s{leaf}\"\n            let tabs = \"\\t\" |&gt; Seq.replicate d |&gt; String.concat \"\"\n            sprintf \"%s\" (tabs + s)\n\n        let fBranch p d i branch =\n            let branch = branch |&gt; branchToString\n            let p = p @ [ i ] |&gt; List.map string |&gt; String.concat \".\"\n            let s = $\"{p} %s{branch}\"\n            let tabs = \"\\t\" |&gt; Seq.replicate d |&gt; String.concat \"\"\n            sprintf \"%s\" (tabs + s)\n\n        let tost acc s = $\"{acc}\\n{s}\"\n\n        tree |&gt; mapi fLeaf fBranch |&gt; fold tost tost \"\"\n\n\n    \/\/\/ Iterate through a tree, using\n    \/\/\/ - fLeaf: to handle the leaf type and\n    \/\/\/ - fBranch: to handle the branch type\n    \/\/\/ the handle functions also get all the tree indexes:\n    \/\/\/ - p: a sequence of parent indexes\n    \/\/\/ - d: the depth of the tree item\n    \/\/\/ - b: the breath of the tree item\n    \/\/\/ - i: the item number in the parent\n    let iteri fLeaf fBranch (tree: GeneralTree&lt;_, _&gt;) =\n        let rec loop fLeaf fBranch p d b i tree =\n            let recurse = loop fLeaf fBranch\n\n            match tree with\n            | Empty -&gt; b\n            | Leaf leaf -&gt;\n                leaf |&gt; fLeaf p b d i\n                b\n            | Branch (branch, trees) -&gt;\n                branch |&gt; fBranch p b d i\n                let p = [ i ] |&gt; List.append p\n                let d = d + 1\n\n                trees\n                |&gt; Seq.mapi (fun i t -&gt; i, t)\n                |&gt; Seq.fold (fun b (i, tree) -&gt; recurse p d (b + 1) i tree) b\n\n        loop fLeaf fBranch [] 0 0 0 tree |&gt; ignore\n\n\n    \/\/\/ Transform a tree to a table\n    let toTable (tree: GeneralTree&lt;_, _&gt;) =\n        let tableCell c item = item |&gt; c |&gt; Seq.singleton\n\n        let rec loop table tree =\n            match tree with\n            | Empty -&gt; Seq.empty\n            | Leaf leaf -&gt;\n                let tc = leaf |&gt; tableCell Leaf\n\n                if table |&gt; Seq.isEmpty then\n                    tc |&gt; Seq.singleton\n                else\n                    table |&gt; Seq.map (fun row -&gt; tc |&gt; Seq.append row)\n            | Branch (branch, trees) -&gt;\n                if trees |&gt; Seq.isEmpty then\n                    (branch, Seq.empty)\n                    |&gt; tableCell Branch\n                    |&gt; Seq.singleton\n                else\n                    trees\n                    |&gt; Seq.collect (loop table)\n                    |&gt; Seq.map (fun row -&gt;\n                        let tc = (branch, Seq.empty) |&gt; tableCell Branch\n                        row |&gt; Seq.append tc)\n\n        loop Seq.empty tree\n\n\n    \/\/\/ Get all distinct branhces and leaves of a tree\n    let distinct (tree: GeneralTree&lt;_, _&gt;) =\n        let addItem c acc item =\n            let item = item |&gt; c\n\n            if acc |&gt; Seq.contains item then\n                acc\n            else\n                item |&gt; Seq.singleton |&gt; Seq.append acc\n\n        let fLeaf = addItem Leaf\n        let fBranch = addItem (fun b -&gt; (b, Seq.empty) |&gt; Branch)\n        fold fLeaf fBranch Seq.empty tree\n\n\n    \/\/\/ Detect wheter in a tree there are any cyclic\n    \/\/\/ tree sections\n    let detectCycles (tree: GeneralTree&lt;_, _&gt;) =\n        tree\n        |&gt; toTable\n        |&gt; Seq.fold\n            (fun acc row -&gt;\n                row\n                |&gt; Seq.distinct\n                |&gt; Seq.fold\n                    (fun acc t -&gt;\n                        row\n                        |&gt; Seq.fold\n                            (fun (n, acc') t' -&gt;\n                                match n with\n                                | _ when n = 0 &amp;&amp; t' = t -&gt;\n                                    (1, t' |&gt; Seq.singleton)\n                                | _ when n = 1 &amp;&amp; t' &lt;&gt; t -&gt;\n                                    (1, t' |&gt; Seq.singleton |&gt; Seq.append acc')\n                                | _ when n = 1 &amp;&amp; t' = t -&gt;\n                                    (2, t' |&gt; Seq.singleton |&gt; Seq.append acc')\n                                | _ -&gt; (n, acc'))\n                            (0, Seq.empty)\n                        |&gt; Seq.singleton\n                        |&gt; Seq.append acc)\n                    Seq.empty\n                |&gt; Seq.filter (fun (n, _) -&gt; n = 2)\n                |&gt; Seq.map snd\n                |&gt; Seq.append acc)\n            Seq.empty\n\n\n    let empty = Empty\n\n\n    \/\/\/ Initialize a tree with a branch\n    let init branch = (branch, Seq.empty) |&gt; Branch\n\n\n    \/\/\/ Add an item (leaf or branch) to a branch\n    let addTobranch item branch tree =\n        let fBranch b tree =\n            if b &lt;&gt; branch then\n                (b, tree)\n            else\n                (branch, item |&gt; Seq.singleton |&gt; Seq.append tree)\n            |&gt; Branch\n\n        cata Leaf fBranch tree\n\n\n    \/\/\/ Add a leaf to a branch\n    let addLeafTobranch root leaf =\n        let item = leaf |&gt; Leaf\n        addTobranch item root\n\n\n    \/\/\/ Add a branch to a branch\n    let addBranchTobranch root branch =\n        let item = branch |&gt; init\n        addTobranch item root\n\n<\/code><\/pre>\n\n\n\n<p>This is a lot of code but it enables a number of general purposes:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Map a tree to a different kind of tree<\/li><li>Fold a tree into a single type<\/li><li>Iterate over a tree<\/li><li>Map a tree to a table representation<\/li><li>Detect cycles in a tree<\/li><li>Add branches and leaves to a tree<\/li><\/ul>\n\n\n\n<p>From this code it is then easy to create the code for, for example, the &#8220;simple tree&#8221; where there are just nodes, i.e. there is no distinction between a leaf and a branch.<\/p>\n\n\n\n<pre class=\"wp-block-code has-black-color has-text-color\"><code lang=\"fsharp\" class=\"language-fsharp\">[&lt;RequireQualifiedAccess&gt;]\nmodule SimpleTree =\n\n\n    module Tree = GeneralTree\n\n\n    \/\/\/ Catamorphism of a tree, using:\n    \/\/\/ - fNode: that handles a node type and\n    \/\/\/ - the recursed results of handling the subtrees.\n    let cata fNode (tree: SimpleTree&lt;_&gt;) : SimpleTree&lt;_&gt; =\n        let fLeaf leaf = fNode leaf Seq.empty\n        Tree.cata fLeaf fNode tree\n\n\n    \/\/\/ A fold over a tree, using\n    \/\/\/ - fNode: that handles a node type and the accumulator\n    let fold fNode acc (tree: SimpleTree&lt;_&gt;) : SimpleTree&lt;_&gt; =\n        Tree.fold fNode fNode acc tree\n\n\n    \/\/\/ Foldback of a tree, using:\n    \/\/\/ - fNode: that handles a node type and the accumulator\n    let foldBack fNode (tree: SimpleTree&lt;_&gt;) acc =\n        Tree.foldBack fNode fNode tree acc\n\n\n    \/\/\/ Map the node type of a tree, using\n    \/\/\/ - fNode: to map the node type from a -&gt; b\n    let map fNode (tree: SimpleTree&lt;_&gt;) : SimpleTree&lt;'Node&gt; =\n        Tree.map fNode fNode tree\n\n\n    \/\/\/ Iterate through a tree, using\n    \/\/\/ - fNode: to handle the node type and\n    let iter fNode (tree: SimpleTree&lt;_&gt;) = Tree.iter fNode fNode tree\n\n\n    \/\/\/ Map the node type of a tree, using\n    \/\/\/ - fNode: to map the node type from a -&gt; b\n    \/\/\/ the map functions also get all the tree indexes:\n    \/\/\/ - p: a sequence of parent indexes\n    \/\/\/ - d: the depth of the tree item\n    \/\/\/ - i: the item number in the parent\n    let mapi fNode (tree: SimpleTree&lt;_&gt;) : SimpleTree&lt;_&gt; =\n        Tree.mapi fNode fNode tree\n\n\n    \/\/\/ Gives an nice string representation of a tree\n    \/\/\/ incorperating all tree specific indexes like:\n    \/\/\/ - parent indexes\n    \/\/\/ - depth (by indentation)\n    \/\/\/ - breath (the count) and\n    \/\/\/ - the item number in the list of the parent\n    let toString nodeToString (tree: SimpleTree&lt;_&gt;) =\n        Tree.toString nodeToString nodeToString tree\n\n\n    \/\/\/ Iterate through a tree, using\n    \/\/\/ - fNode: to handle the node type\n    \/\/\/ the handle functions also get all the tree indexes:\n    \/\/\/ - p: a sequence of parent indexes\n    \/\/\/ - d: the depth of the tree item\n    \/\/\/ - b: the breath of the tree item\n    \/\/\/ - i: the item number in the parent\n    let iteri fNode (tree: SimpleTree&lt;_&gt;) = Tree.iteri fNode fNode tree\n\n\n    \/\/\/ Transform a tree to a table\n    let toTable (tree: SimpleTree&lt;_&gt;) : SimpleTree&lt;_&gt; seq seq =\n        Tree.toTable tree\n\n    \/\/\/ Get all distinct nodes of a tree\n    let distinct (tree: SimpleTree&lt;_&gt;) : SimpleTree&lt;_&gt; seq = Tree.distinct tree\n\n\n    \/\/\/ Detect wheter in a tree there are any cyclic\n    \/\/\/ tree sections\n    let detectCycles (tree: SimpleTree&lt;_&gt;) : SimpleTree&lt;_&gt; seq seq =\n        Tree.detectCycles tree\n\n\n    \/\/\/ Initialize a tree with a node\n    let init node : SimpleTree&lt;_&gt; = (node, Seq.empty) |&gt; Branch\n\n\n    \/\/\/ Add a node\n    let add item node (tree: SimpleTree&lt;_&gt;) : SimpleTree&lt;_&gt; =\n        Tree.addBranchTobranch item node tree\n\n<\/code><\/pre>\n\n\n\n<p>As the above code shows, there is very little work needed to handle a simple tree as a subtype of a general tree. For a binary tree somewhat more work is needed. But still everything is just mapping of types and functions to the general tree type and all logic is handled by the general tree module.<\/p>\n\n\n\n<pre class=\"wp-block-code has-black-color has-text-color\"><code lang=\"fsharp\" class=\"language-fsharp\">[&lt;RequireQualifiedAccess&gt;]\nmodule BinaryTree =\n\n    module Tree = GeneralTree\n\n\n    let empty = BinaryTree.Empty\n\n\n    let node a = (a, empty, empty) |&gt; Node\n\n    \/\/\/ Helper function to map a binary tree\n    \/\/\/ to a general tree\n    let mapToGeneralTree (tree: BinaryTree&lt;'Node&gt;) : GeneralTree&lt;'Node, 'Node&gt; =\n        let rec recurse tree =\n            match tree with\n            | BinaryTree.Empty -&gt; GeneralTree.empty\n            | Node (node, BinaryTree.Empty, BinaryTree.Empty) -&gt;\n                node |&gt; GeneralTree.init\n            | Node (node, left, right) -&gt;\n                node\n                |&gt; GeneralTree.init\n                |&gt; GeneralTree.addTobranch (recurse left) node\n                |&gt; GeneralTree.addTobranch (recurse right) node\n\n        recurse tree\n\n    \/\/\/ Helper function to map a general tree to\n    \/\/\/ a binary tree\n    let mapToBinaryTree (tree: GeneralTree&lt;_, _&gt;) : BinaryTree&lt;_&gt; =\n        let rec recurse tree =\n            match tree with\n            | GeneralTree.Empty -&gt; empty\n            | Branch (branch, trees) when trees |&gt; Seq.length = 0 -&gt;\n                branch |&gt; node\n            | Branch (branch, trees) when trees |&gt; Seq.length = 2 -&gt;\n                Node(\n                    branch,\n                    trees |&gt; Seq.item 0 |&gt; recurse,\n                    trees |&gt; Seq.item 1 |&gt; recurse\n                )\n            | _ -&gt; $\"{tree} is not a valid binary tree\" |&gt; failwith\n\n        tree |&gt; recurse\n\n\n    let applyMap f fBranch tree =\n        let fLeaf _ = $\"not supported\" |&gt; failwith\n\n        tree\n        |&gt; mapToGeneralTree\n        |&gt; f fLeaf fBranch\n        |&gt; mapToBinaryTree\n\n\n    let applyFold f fBranch acc tree =\n        let fLeaf _ = $\"not supported\" |&gt; failwith\n\n        tree |&gt; mapToGeneralTree |&gt; f fLeaf fBranch acc\n\n\n    let applyIter f fBranch acc tree =\n        let fLeaf _ = $\"not supported\" |&gt; failwith\n\n        tree |&gt; mapToGeneralTree |&gt; f fLeaf fBranch\n\n\n    \/\/\/ Catamorphism of a tree, using:\n    \/\/\/ - fLeaf: that handles a leaf type and\n    \/\/\/ - fBranch: that handles a branch type and\n    \/\/\/ the recursed results of handling the subtrees.\n    let cata fNode (tree: BinaryTree&lt;_&gt;) =\n        let fBranch node nodes =\n            if nodes |&gt; Seq.length &lt;&gt; 2 then\n                $\"not supported\" |&gt; failwith\n            else\n                fNode\n                    node\n                    (nodes |&gt; Seq.item 0 |&gt; mapToBinaryTree)\n                    (nodes |&gt; Seq.item 1 |&gt; mapToBinaryTree)\n                |&gt; mapToGeneralTree\n\n        tree |&gt; applyMap Tree.cata fBranch\n\n\n    \/\/\/ A fold over a tree, using\n    \/\/\/ - fLeaf: that handles a leaf type and the accumulator\n    \/\/\/ - fBranch: that handles a branch type and the accumulator\n    let fold fNode acc (tree: BinaryTree&lt;_&gt;) =\n        let fBranch acc node = node |&gt; fNode acc\n\n        tree |&gt; applyFold GeneralTree.fold fBranch acc\n\n\n    \/\/\/ Foldback of a tree, using:\n    \/\/\/ - fLeaf: that handles a leaf type and the accumulator\n    \/\/\/ - fBranch: that handles a branch type and the accumulator\n    let foldBack fNode (tree: BinaryTree&lt;_&gt;) acc =\n        let fBranch acc node = node |&gt; fNode acc\n\n        let foldBack fLeaf fBranch acc tree =\n            GeneralTree.foldBack fLeaf fBranch tree acc\n\n        tree |&gt; applyFold foldBack fBranch acc\n\n\n    \/\/\/ Map the leaf and branch types of a tree, using\n    \/\/\/ - fLeaf: to map the leaf type from a -&gt; b and\n    \/\/\/ - fBranch: to map a branch from c -&gt; d\n    let map fNode (tree: BinaryTree&lt;_&gt;) : BinaryTree&lt;_&gt; =\n        tree |&gt; applyMap Tree.map fNode\n\n\n    \/\/\/ Iterate through a tree, using\n    \/\/\/ - fLeaf: to handle the leaf type and\n    \/\/\/ - fBranch: to handle the branch type\n    let iter fNode (tree: BinaryTree&lt;_&gt;) = tree |&gt; applyIter Tree.iter fNode\n\n\n    \/\/\/ Map the leaf and branch types of a tree, using\n    \/\/\/ - fLeaf: to map the leaf type from a -&gt; b and\n    \/\/\/ - fBranch: to map a branch from c -&gt; d\n    \/\/\/ the map functions also get all the tree indexes:\n    \/\/\/ - p: a sequence of parent indexes\n    \/\/\/ - d: the depth of the tree item\n    \/\/\/ - i: the item number in the parent\n    let mapi fNode (tree: BinaryTree&lt;_&gt;) : BinaryTree&lt;_&gt; =\n        tree |&gt; applyMap Tree.mapi fNode\n\n\n    \/\/\/ Gives an nice string representation of a tree\n    \/\/\/ incorperating all tree specific indexes like:\n    \/\/\/ - parent indexes\n    \/\/\/ - depth (by indentation)\n    \/\/\/ - breath (the count) and\n    \/\/\/ - the item number in the list of the parent\n    let toString nodeToString (tree: BinaryTree&lt;_&gt;) =\n        tree\n        |&gt; mapToGeneralTree\n        |&gt; Tree.toString nodeToString nodeToString\n\n\n    \/\/\/ Iterate through a tree, using\n    \/\/\/ - fLeaf: to handle the leaf type and\n    \/\/\/ - fBranch: to handle the branch type\n    \/\/\/ the handle functions also get all the tree indexes:\n    \/\/\/ - p: a sequence of parent indexes\n    \/\/\/ - d: the depth of the tree item\n    \/\/\/ - b: the breath of the tree item\n    \/\/\/ - i: the item number in the parent\n    let iteri fNode (tree: SimpleTree&lt;_&gt;) = tree |&gt; applyIter Tree.iteri fNode\n\n\n    \/\/\/ Transform a tree to a table\n    let toTable (tree: BinaryTree&lt;_&gt;) : BinaryTree&lt;_&gt; seq seq =\n        tree\n        |&gt; mapToGeneralTree\n        |&gt; Tree.toTable\n        |&gt; Seq.map (Seq.map mapToBinaryTree)\n\n    \/\/\/ Get all distinct branhces and leaves of a tree\n    let distinct (tree: BinaryTree&lt;_&gt;) : BinaryTree&lt;_&gt; seq =\n        tree\n        |&gt; mapToGeneralTree\n        |&gt; Tree.distinct\n        |&gt; Seq.map mapToBinaryTree\n\n\n    \/\/\/ Detect wheter in a tree there are any cyclic\n    \/\/\/ tree sections\n    let detectCycles (tree: BinaryTree&lt;_&gt;) : BinaryTree&lt;_&gt; seq seq =\n        tree\n        |&gt; mapToGeneralTree\n        |&gt; Tree.detectCycles\n        |&gt; Seq.map (Seq.map mapToBinaryTree)\n\n\n    \/\/\/ Initialize a tree with a branch\n    let init = node\n\n\n    \/\/\/ Add an item (leaf or branch) to a branch\n    let add node origin (tree: BinaryTree&lt;_&gt;) : BinaryTree&lt;_&gt; =\n        tree\n        |&gt; mapToGeneralTree\n        |&gt; Tree.addBranchTobranch node origin\n        |&gt; mapToBinaryTree<\/code><\/pre>\n\n\n\n<p>Currently, the code resides at a <a href=\"https:\/\/gist.github.com\/halcwb\/ec64ae3a4e1c2e1257096e5d5766e559\" target=\"_blank\" rel=\"noreferrer noopener\">gist<\/a>. However, it would be useful to turn this into a general purpose library. I think.<\/p>\n<div class=\"pvc_clear\"><\/div><p id=\"pvc_stats_358\" class=\"pvc_stats all  \" data-element-id=\"358\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/informedica.nl\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p><div class=\"pvc_clear\"><\/div>","protected":false},"excerpt":{"rendered":"<p>A tree is a very common datastructure. I stumbled upon this subject because of a requirement that is needed for a mathematical solution. This solution needs to keep track of changes that start with a single change but can have multiple effects. Each effect, i.e. change, can result in turn into multiple changes, hence the &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/informedica.nl\/?p=358\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Trees&#8221;<\/span><\/a><\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_358\" class=\"pvc_stats all  \" data-element-id=\"358\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/informedica.nl\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-358","post","type-post","status-publish","format-standard","hentry","category-general"],"_links":{"self":[{"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/posts\/358","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/informedica.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=358"}],"version-history":[{"count":12,"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/posts\/358\/revisions"}],"predecessor-version":[{"id":374,"href":"https:\/\/informedica.nl\/index.php?rest_route=\/wp\/v2\/posts\/358\/revisions\/374"}],"wp:attachment":[{"href":"https:\/\/informedica.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=358"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/informedica.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=358"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/informedica.nl\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=358"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}