summaryrefslogtreecommitdiff
path: root/lib/tipper.mli
diff options
context:
space:
mode:
authorFederico Igne <undyamon@disroot.org>2024-01-28 23:41:50 +0100
committerFederico Igne <undyamon@disroot.org>2024-01-28 23:41:50 +0100
commit633fb26ed21f7208517aa29dbaab9f0cf3bb2047 (patch)
tree2b6ae4402b61a03886f527355a9b480900598bdf /lib/tipper.mli
parent05e1cc51b2fb0824580925b55319377305105c44 (diff)
downloadsandy-633fb26ed21f7208517aa29dbaab9f0cf3bb2047.tar.gz
sandy-633fb26ed21f7208517aa29dbaab9f0cf3bb2047.zip
feat: add generic tree zipper data structure
Diffstat (limited to 'lib/tipper.mli')
-rw-r--r--lib/tipper.mli93
1 files changed, 93 insertions, 0 deletions
diff --git a/lib/tipper.mli b/lib/tipper.mli
new file mode 100644
index 0000000..f2a8288
--- /dev/null
+++ b/lib/tipper.mli
@@ -0,0 +1,93 @@
1open Base
2
3(** Tree zippers.
4
5 A zipper represents {b a paused traversal} of a certain data
6 structure. A tree zipper of type ['a tipper] represents a zipper
7 over a generic tree of ['a] elements.
8
9 One can access the {b focused element} of the zipper with [focus].
10 The focus of a zipper is also known as the the {b cursor} of the
11 zipper. The cursor can be moved [up] to the parent node, if any, or
12 [down] to one of the selected children; [left] and [right] can be
13 used to select adjacent children. To select the right (resp. left)
14 sibling of the current cursor, for example, one should go [up], move
15 [right] (resp. [left]) and [down] again.
16
17 Elements can be added to the children of the current cursor with
18 [push] and removed with [pop].
19
20 In this particular implementation, there is no such thing as an {b
21 empty} tree zipper. *)
22
23type !+'a tipper
24(** A zipper is represented as an element of type ['a], a parent ['a
25 tipper] (with a hole) and a sequences of ['a tipper] children. *)
26
27type !+'a t = 'a tipper
28(** An alias for the ['a tipper] type. *)
29
30val create : 'a -> 'a tipper
31(** [create a] returns a new tipper with a single node containing [a]. *)
32
33val focus : 'a tipper -> 'a
34(** Returns the element pointed by the cursor *)
35
36val is_root : 'a tipper -> bool
37(** Returns whether the cursor is at the root of the tree. *)
38
39val is_leaf : 'a tipper -> bool
40(** Returns whether the cursor is pointing to a leaf (a node with no
41 children). *)
42
43val is_far_left : 'a tipper -> bool
44(** Returns whether the leftmost child is selected. *)
45
46val is_far_right : 'a tipper -> bool
47(** Returns whether the rightmost child is selected. *)
48
49(** {1 Moving the cursor} *)
50
51val left : 'a tipper -> 'a tipper
52(** Select the children on the left. *)
53
54val far_left : 'a tipper -> 'a tipper
55(** Select the children on the far left. *)
56
57val right : 'a tipper -> 'a tipper
58(** Select the children on the right. *)
59
60val far_right : 'a tipper -> 'a tipper
61(** Select the children on the far right. *)
62
63val up : 'a tipper -> 'a tipper
64(** Move cursor to the parent node, if any. *)
65
66val up_while : f:('a tipper -> bool) -> 'a tipper -> 'a tipper
67(** [up_while ~f t] moves the cursor in [t] up while the predicate [f]
68 is satisfied. *)
69
70val root : 'a tipper -> 'a tipper
71(** Move the cursor up to the root of the tree. *)
72
73val down : 'a tipper -> 'a tipper
74(** Move cursor to the selected child node, if any. *)
75
76(** {1 Modifying the tree zipper} *)
77
78val set_focus : 'a -> 'a tipper -> 'a tipper
79(** [set_focus a t] sets the element at the cursor position in [t] to
80 [a]. *)
81
82val push : 'a tipper -> 'a tipper -> 'a tipper
83(** [push t1 t2] adds [t1] as a subtree child of the node in [t2]
84 pointed by the cursor, so that [t1] is the newly selected child. *)
85
86val pop : 'a tipper -> 'a tipper option * 'a tipper
87(** [pop t] removes the subtree associated with the selected child.
88 Returns the subtree as a first element and the modified [t] as the
89 second. *)
90
91(** {1 Consuming the tree zipper} *)
92
93val fold : a:'a -> f:('a -> 'b tipper -> 'a) -> 'b tipper -> 'a