Definition cmp_cmp (x y: comparison): { x = y } + { x <> y } :=
  (* instead of being lazy with tactics, let's try to make as short a term as possible *)
  match x, y return { x = y } + { x <> y } with
  | Lt, Lt | Gt, Gt | Eq, Eq => left _ (refl_equal _)
  | a, b => right _ (
      match a, b
      return match a, b with Lt, Lt | Gt, Gt | Eq, Eq => True | _, _ => ~(a = b) end with
      | Lt, Lt | Gt, Gt | Eq, Eq => I
      | Lt, _ => fun q => match q in _ = Lt with refl_equal => I end
      | Gt, _ => fun q => match q in _ = Gt with refl_equal => I end
      | Eq, _ => fun q => match q in _ = Eq with refl_equal => I end
      end
    )
  end.(* todo: derive this using the new equality Schemes *)

Fixpoint nat_cmp (x y: nat) {struct x}: comparison :=
  match x, y with
  | 0, 0 => Eq
  | 0, S _ => Lt
  | S _, 0 => Gt
  | S x', S y' => nat_cmp x' y'
  end.Ltac cset e := let v := fresh in set (v := e); clearbody v.Ltac cset' e := let v := fresh in set (v := e) in *; clearbody v.Ltac extro x := generalize x; clear x.Definition unsum_bool (A B: Prop) (sb: sumbool A B): bool := if sb then true else false.Definition decision (P: Prop): Set := { P } + { ~ P }.Definition predDecider (T: Set) (P: T -> Prop): Type := forall t, decision (P t).

(* Specifications: *)
Lemma negb_inv (b b': bool): negb b = negb b' -> b = b'.
Lemma negb_negb (b: bool): negb (negb b) = b.