(* BEGIN NEW MATERIAL *)

Class heightable (A : Type) : Type := Heightable {
  height : A -> nat;
  is_height_zero : forall a : A, {height a = 0} + {height a <> 0} (* Should run in O(1) time for trees *)
 }.(* BEGIN NEW MATERIAL *)

Class heightable (A : Type) : Type := Heightable {
  height : A -> nat;
  is_height_zero : forall a : A, {height a = 0} + {height a <> 0} (* Should run in O(1) time for trees *)
 }.(* BEGIN NEW MATERIAL *)

Class heightable (A : Type) : Type := Heightable {
  height : A -> nat;
  is_height_zero : forall a : A, {height a = 0} + {height a <> 0} (* Should run in O(1) time for trees *)
 }.(* BEGIN NEW MATERIAL *)

Class heightable (A : Type) : Type := Heightable {
  height : A -> nat;
  is_height_zero : forall a : A, {height a = 0} + {height a <> 0} (* Should run in O(1) time for trees *)
 }.Definition is_height_zero_spec {A : Type} (height : A -> nat) : Type :=
  forall a : A, {height a = 0} + {height a <> 0}.Definition list_height {A} `{heightable A} (LA : list A) : nat :=
  fold_right max 0 (map height LA).Fixpoint list_is_height_zero_bool {A} `{heightable A} (L : list A) : bool :=
  match L with
   | nil => true
   | a :: L' =>
      if is_height_zero a then list_is_height_zero_bool L' else false
  end.Instance list_heightable {A} `{heightable A} : heightable (list A).Class decomposible (A : Type) : Type := Decomposible {
  decompose : A -> (A * A)
 }.Class decomposible (A : Type) : Type := Decomposible {
  decompose : A -> (A * A)
 }.Class decomposible (A : Type) : Type := Decomposible {
  decompose : A -> (A * A)
 }.Class roundableLeft (A : Type) : Type := RoundableLeft {
   roundL : nat -> A -> option A
 }.Class roundableLeft (A : Type) : Type := RoundableLeft {
   roundL : nat -> A -> option A
 }.Class roundableLeft (A : Type) : Type := RoundableLeft {
   roundL : nat -> A -> option A
 }.Class roundableRight (A : Type) : Type := RoundableRight {
   roundR : nat -> A -> option A
 }.Class roundableRight (A : Type) : Type := RoundableRight {
   roundR : nat -> A -> option A
 }.Class roundableRight (A : Type) : Type := RoundableRight {
   roundR : nat -> A -> option A
 }.Class avgable (A : Type) : Type := Avgable {
    avg : nat -> A -> A -> option A
 }.Class avgable (A : Type) : Type := Avgable {
    avg : nat -> A -> A -> option A
 }.Class avgable (A : Type) : Type := Avgable {
    avg : nat -> A -> A -> option A
 }.

Lemma lub_assoc : forall x y z, lub (lub x y) z = lub x (lub y z).