Module Relude_TreeZipper
type t('a)
=
{
ancestors: list((list(Relude_Tree.t('a)), 'a, list(Relude_Tree.t('a)))),
leftSiblings: list(Relude_Tree.t('a)),
focus: 'a,
rightSiblings: list(Relude_Tree.t('a)),
children: list(Relude_Tree.t('a)),
}
;A zipper for a non-empty multi-way/rose tree
The leftSiblings are stored in reverse order for O(1) sideways movements.
Based on the ideas/implementation from Tony Morris' talk here: http://data.tmorris.net/talks/zippers/bd054c210649101b84662c614fc45af3c27a5eef/zippers.pdf
let pure: 'a => t('a);
Creates a tree zipper containing a single item
let singleton: 'a => t('a);
Alias for pure
let make: a. list((list(Relude_Tree.t('a)), 'a, list(Relude_Tree.t('a)))) => list(Relude_Tree.t('a)) => 'a => list(Relude_Tree.t('a)) => list(Relude_Tree.t('a)) => t('a);
Constructs a tree zipper from parts
let makeWithLabels: a. ancestors:list((list(Relude_Tree.t('a)), 'a, list(Relude_Tree.t('a)))) => leftSiblings:list(Relude_Tree.t('a)) => focus:'a => rightSiblings:list(Relude_Tree.t('a)) => children:list(Relude_Tree.t('a)) => t('a);
Constructs a tree zipper from (labelled) parts
let fromTree: a. Relude_Tree.t('a) => t('a);
Converts a Tree into a Tree Zipper
let getAncestors: a. t('a) => list((list(Relude_Tree.t('a)), 'a, list(Relude_Tree.t('a))));
Gets the list of ancestor levels for the given TreeZipper
let getFocusValue: a. t('a) => 'a;
Gets the value at the focus of the TreeZipper
let tapFocusValue: a. ('a => unit) => t('a) => t('a);
Applies a side-effect function with the current focus value, and returns the zipper unchanged
let getFocusTree: a. t('a) => Relude_Tree.t('a);
Gets the value and children at the focus of the TreeZipper as a Tree
let getLeftSiblings: a. t('a) => list(Relude_Tree.t('a));
Gets the siblings to the left of the focus value, in reverse order. (the first item of the resulting list is the item that is immediately to the left of the focus).
let getLeftSiblingsInOrder: a. t('a) => list(Relude_Tree.t('a));
Gets the siblings to the left of the focus value, in order. (the first item of the resulting list is the item that is the leftmost sibling (furthest from focus))
let setLeftSiblings: a. list(Relude_Tree.t('a)) => t('a) => option(t('a));
Sets the left siblings from a reversed list (where the first item of the list should be closest to the focus)
let setLeftSiblingsFromInOrder: a. list(Relude_Tree.t('a)) => t('a) => option(t('a));
Sets the left siblings from an in-order list (where the first item of the list should be farthest from the focus)
let getRightSiblings: a. t('a) => list(Relude_Tree.t('a));
Gets the siblings to the right of the current focus
let setRightSiblings: a. list(Relude_Tree.t('a)) => t('a) => option(t('a));
Sets the right siblings from a reversed list (where the first item of the list should be closest to the focus)
let getChildren: a. t('a) => list(Relude_Tree.t('a));
Gets the children sub-trees of the current focus
let moveLeftWithClamp: a. t('a) => t('a);
Moves to the left, unless we are already at the leftmost item
let moveLeftTimesWithClamp: a. int => t('a) => t('a);
Move the focus to the left a number of times, stopping if the leftmost sibling is reached
let moveRightWithClamp: a. t('a) => t('a);
Moves the zipper to the right one time, unless we are already at the rightmost item
let moveRightTimesWithClamp: a. int => t('a) => t('a);
Move the focus to the right a number of times, stopping if the rightmost sibling is reached
let moveUpTimes: a. int => t('a) => option(t('a));
Moves the zipper up a number of times (if possible)
let moveUpTimesWithClamp: a. int => t('a) => t('a);
Moves the zipper up a number of times, stopping if the top is reached
let moveDownWithClamp: a. t('a) => t('a);
Moves the zipper down one time, unless there are no children
let moveDownToBottom: a. t('a) => t('a);
Moves the zipper to focus the bottom of the tree (on the left-most child branches)
let moveDownTimes: a. int => t('a) => option(t('a));
Moves the focus down a number of times (if possible)
let moveDownTimesWithClamp: a. int => t('a) => t('a);
Moves the zipper down a number of times, stopping when we get as low as we can, staying on the left-most child branches.
type movement
=[
|
`Up(int)
|
`UpWithClamp(int)
|
`UpToTop
|
`Down(int)
|
`DownWithClamp(int)
|
`DownToBottom
|
`Left(int)
|
`LeftWithClamp(int)
|
`LeftToStart
|
`Right(int)
|
`RightWithClamp(int)
|
`RightToEnd
]
;Types of movements we can make in a TreeZipper
let moveBy: a. BsBastet.List.Foldable.t(movement) => t('a) => option(t('a));
Applies a list of movement commands to a zipper
let foldBy: a b. BsBastet.List.Foldable.t(movement) => ('b => 'a => 'b) => 'b => t('a) => option((t('a), 'b));
Applies a list of movement commands to a zipper and collects an accumulated value when visiting each new focus
let map: a b. ('a => 'b) => t('a) => t('b);
Converts a zipper of 'a to a zipper of 'b using a pure function
include { ... };
module BsFunctorExtensions: { ... };
let findInFocus: a. ('a => bool) => t('a) => option(t('a));
let findInFocusAndChildren: a. ('a => bool) => t('a) => option(t('a));
Finds a value in the curernt focus and recursively the children. Equivalent to a depth first search in the currently focused tree.
let findLeft: a. ?checkFocus:bool => ('a => bool) => t('a) => option(t('a));
Attempts to find a value by searching the current focus and left siblings
let findRight: a. ?checkFocus:bool => ('a => bool) => t('a) => option(t('a));
Attempts to find a value by searching the current focus and right siblings
let findLeftOrRight: a. ?checkFocus:bool => ('a => bool) => t('a) => option(t('a));
Attempts to find a value by searching the current focus, then the left siblings from the focus outward, then the right siblings from the focus outward.
let findUp: a. ('a => bool) => t('a) => option(t('a));
Attempts to find a value by moving up a level, then searching left and right on the parent level, then progressing upward.
let findDown: a. ('a => bool) => t('a) => option(t('a));
Attempts to find a value by moving down a level, then searching left and right on the child level, then progressing downward.
let find: a. ('a => bool) => t('a) => option(t('a));
Attempts to find a value anywhere in the zipper, left/right/up/down
let insertTreeWithPushLeft: a. Relude_Tree.t('a) => t('a) => option(t('a));
Inserts a new tree, and pushes the current focus to the left
let insertWithPushLeft: a. 'a => t('a) => option(t('a));
Inserts a new value (singleton tree), and pushes the current focus to the left
let insertTreeWithPushRight: a. Relude_Tree.t('a) => t('a) => option(t('a));
Inserts a new tree, and pushes the current focus to the right
let insertWithPushRight: a. 'a => t('a) => option(t('a));
Inserts a new value (singleton tree), and pushes the current focus to the right
let deleteWithPullLeft: a. t('a) => option(t('a));
Deletes the tree at the focus, and pulls the left sibling into focus (if possible)
let deleteWithPullRight: a. t('a) => option(t('a));
Deletes the tree at the focus, and pulls the right sibling into focus (if possible)
let delete: a. t('a) => option(t('a));
Attempts to delete by deleting and pulling from the left. If there is no item on the left, it tries to pull from the right. If there is no item on the right, it moves the focus up a level, discarding the current focus and children.
let showBy: a. ('a => string) => t('a) => string;