[@@@warning "-9"] module Append = struct type 'a t' = | Leaf of 'a | Node of { a : 'a t' ; b : 'a t' ; size : int ; full : bool ; } type 'a t = | Empty | Full of 'a t' let node (a, b, size, full) = Node {a;b;size;full} let rec exists' f = function | Leaf s' when f s' -> true | Leaf _ -> false | Node{a;b} -> exists' f a || exists' f b let exists f = function | Empty -> false | Full x -> exists' f x let rec exists_path' f = function | Leaf x -> if f x then Some [] else None | Node {a;b} -> ( match exists_path' f a with | Some a -> Some (false :: a) | None -> ( match exists_path' f b with | Some b -> Some (true :: b) | None -> None ) ) let exists_path f = function | Empty -> None | Full x -> exists_path' f x let empty : 'a t = Empty let size' = function | Leaf _ -> 1 | Node {size} -> size let size = function | Empty -> 0 | Full x -> size' x let rec append' x = function | Leaf e -> node (Leaf e, Leaf x, 1, true) | Node({full=true;size}) as n -> node(n, Leaf x, size + 1, false) | Node({a=Node a;b;full=false} as n) -> ( match append' x b with | Node{full=false} as b -> Node{n with b} | Node({full=true} as b) -> Node{n with b = Node b ; full = b.size = a.size} | Leaf _ -> assert false ) | Node{a=Leaf _;full=false} -> assert false let append x = function | Empty -> Full (Leaf x) | Full t -> Full (append' x t) let of_list lst = let rec aux = function | [] -> Empty | hd :: tl -> append hd (aux tl) in aux @@ List.rev lst let rec to_list' t' = match t' with | Leaf x -> [x] | Node {a;b} -> (to_list' a) @ (to_list' b) let to_list t = match t with | Empty -> [] | Full x -> to_list' x let rec fold' leaf node = function | Leaf x -> leaf x | Node {a;b} -> node (fold' leaf node a) (fold' leaf node b) let rec fold_s' : type a b . a -> (a -> b -> a) -> b t' -> a = fun init leaf -> function | Leaf x -> leaf init x | Node {a;b} -> fold_s' (fold_s' init leaf a) leaf b let fold_ne leaf node = function | Empty -> raise (Failure "Tree.Append.fold_ne") | Full x -> fold' leaf node x let fold_s_ne : type a b . a -> (a -> b -> a) -> b t -> a = fun init leaf -> function | Empty -> raise (Failure "Tree.Append.fold_s_ne") | Full x -> fold_s' init leaf x let fold empty leaf node = function | Empty -> empty | Full x -> fold' leaf node x let rec assoc_opt' : ('a * 'b) t' -> 'a -> 'b option = fun t k -> match t with | Leaf (k', v) when k = k' -> Some v | Leaf _ -> None | Node {a;b} -> ( match assoc_opt' a k with | None -> assoc_opt' b k | Some v -> Some v ) let assoc_opt : ('a * 'b) t -> 'a -> 'b option = fun t k -> match t with | Empty -> None | Full t' -> assoc_opt' t' k let rec pp' : _ -> _ -> 'a t' -> unit = fun f ppf t' -> match t' with | Leaf x -> Format.fprintf ppf "%a" f x | Node {a;b} -> Format.fprintf ppf "N(%a , %a)" (pp' f) a (pp' f) b let pp : _ -> _ -> 'a t -> unit = fun f ppf t -> match t with | Empty -> Format.fprintf ppf "[]" | Full x -> Format.fprintf ppf "[%a]" (pp' f) x end