Section COMBINE.
Variables A B C: Type.
Variable f: option A -> option B -> option C.
Hypothesis f_none_none: f None None = None.
Fixpoint xcombine_l (m : t A) {struct m} : t C :=
match m with
| Leaf => Leaf
| Node l o r => Node' (xcombine_l l) (f o None) (xcombine_l r)
end.
Fixpoint xcombine_r (m : t B) {struct m} : t C :=
match m with
| Leaf => Leaf
| Node l o r => Node' (xcombine_r l) (f None o) (xcombine_r r)
end.
Fixpoint combine (m1: t A) (m2: t B) {struct m1} : t C :=
match m1 with
| Leaf => xcombine_r m2
| Node l1 o1 r1 =>
match m2 with
| Leaf => xcombine_l m1
| Node l2 o2 r2 => Node' (combine l1 l2) (f o1 o2) (combine r1 r2)
end
end.
End COMBINE.
Fixpoint xelements (A : Type) (m : t A) (i : positive)
(k: list (positive * A)) {struct m}
: list (positive * A) :=
match m with
| Leaf => k
| Node l None r =>
xelements l (xO i) (xelements r (xI i) k)
| Node l (Some x) r =>
xelements l (xO i)
((prev i, x) :: xelements r (xI i) k)
end.
Definition elements (A: Type) (m : t A) := xelements m xH nil.
Remark xelements_append:
forall A (m: t A) i k1 k2,
xelements m i (k1 ++ k2) = xelements m i k1 ++ k2.
Remark xelements_leaf:
forall A i, xelements (@Leaf A) i nil = nil.
Remark xelements_node:
forall A (m1: t A) o (m2: t A) i,
xelements (Node m1 o m2) i nil =
xelements m1 (xO i) nil
++ match o with None => nil | Some v => (prev i, v) :: nil end
++ xelements m2 (xI i) nil.
Definition xkeys (A: Type) (m: t A) (i: positive) :=
List.map (@fst positive A) (xelements m i nil).
Remark xkeys_leaf:
forall A i, xkeys (@Leaf A) i = nil.
Remark xkeys_node:
forall A (m1: t A) o (m2: t A) i,
xkeys (Node m1 o m2) i =
xkeys m1 (xO i)
++ match o with None => nil | Some v => prev i :: nil end
++ xkeys m2 (xI i).
Remark xelements_empty:
forall (A: Type) (m: t A) i, (forall i, get i m = None) -> xelements m i nil = nil.
Fixpoint xfold (A B: Type) (f: B -> positive -> A -> B)
(i: positive) (m: t A) (v: B) {struct m} : B :=
match m with
| Leaf => v
| Node l None r =>
let v1 := xfold f (xO i) l v in
xfold f (xI i) r v1
| Node l (Some x) r =>
let v1 := xfold f (xO i) l v in
let v2 := f v1 (prev i) x in
xfold f (xI i) r v2
end.
Definition fold (A B : Type) (f: B -> positive -> A -> B) (m: t A) (v: B) :=
xfold f xH m v.
Fixpoint fold1 (A B: Type) (f: B -> A -> B) (m: t A) (v: B) {struct m} : B :=
match m with
| Leaf => v
| Node l None r =>
let v1 := fold1 f l v in
fold1 f r v1
| Node l (Some x) r =>
let v1 := fold1 f l v in
let v2 := f v1 x in
fold1 f r v2
end.

Theorem fold1_spec:
forall (A B: Type) (f: B -> A -> B) (v: B) (m: t A),
fold1 f m v =
List.fold_left (fun a p => f a (snd p)) (elements m) v.