Module TF:=TF'.Definition sinv_prod X := prod X (F X * other -> Prop).Definition guppy_sig := (fun T:Type => T * (F T * other -> Prop) -> Prop).Definition guppy_ty := sigT guppy_sig.Definition guppy_step_ty (Z:guppy_ty) : Type :=
    (sig (fun (x:sinv_prod (projT1 Z)) => projT2 Z x)).Definition guppy_step (Z:guppy_ty) : guppy_ty :=
    existT guppy_sig (guppy_step_ty Z) (guppy_step_prop Z).Definition guppy_base : guppy_ty :=
    existT guppy_sig unit (fun _ => True).Fixpoint guppy (n:nat) : guppy_ty :=
    match n with
    | 0    => guppy_base
    | S n' => guppy_step (guppy n')
    end.Definition sinv (n:nat) : Type := projT1 (guppy n).Definition sinv_prop (n:nat) : prod (sinv n) (F (sinv n) * other -> Prop) -> Prop := projT2 (guppy n).Fixpoint floor (m:nat) (n:nat) (p:sinv (m+n)) : sinv n :=
    match m as m' return forall (p : sinv (m'+n)), sinv n with
    | O => fun p => p
    | S m' => fun p => floor m' n (fst (proj1_sig p))
    end p.Definition knot := { n:nat & F (sinv n) }.Definition k_age (k1 k2:knot) := k_age1 k1 = Some k2.Definition ko_age1 (x:knot * other) :=
    match k_age1 (fst x) with
    | None => None
    | Some a' => Some (a',snd x)
    end.Definition ko_age x y := ko_age1 x = Some y.Definition predicate := { p:knot * other -> Prop | hereditary ko_age p }.Definition app_sinv (n:nat) (p:sinv (S n)) (x:F (sinv n) * other) :=
    snd (proj1_sig p) x.Fixpoint stratifies (n:nat) : sinv n -> Prop :=
    match n as n' return sinv n' -> Prop with
    | 0 => fun _ => True
    | S n' => fun (p:sinv (S n')) =>
          stratifies n' (fst (proj1_sig p)) /\
          forall (k:F (sinv n')) (o:other), snd (proj1_sig p) (k,o) <-> Q (existT (F oo sinv) n' k,o)
    end.

(* Specifications: *)
Lemma stratifies_unique : forall n p1 p2, stratifies n p1 -> stratifies n p2 -> p1 = p2.