(* * Copyright (c) 2009-2011, Andrew Appel, Robert Dockins and Aquinas Hobor. * *)
Local Open Scope nat_scope.
Module Type TY_FUNCTOR.
Parameter F : functor.
Parameter T : Type.
Parameter T_bot : T.
Parameter other : Type.
End TY_FUNCTOR.
Module Type KNOT.
Declare Module TF:TY_FUNCTOR.
Parameter knot : Type.
Parameter ag_knot : ageable knot.
Existing Instance ag_knot.
Existing Instance ag_prod.
Definition predicate := (knot * other) -> T.
Parameter squash : (nat * F predicate) -> knot.
Parameter unsquash : knot -> (nat * F predicate).
Definition approx (n:nat) (p:predicate) : predicate :=
fun w => if le_gt_dec n (level w) then T_bot else p w.

(* Specifications: *)
Axiom squash_unsquash : forall x, squash (unsquash x) = x.
Axiom unsquash_squash : forall n x', unsquash (squash (n,x')) = (n,fmap F (approx n) x').
Axiom knot_level : forall k:knot,
level k = fst (unsquash k).
Axiom knot_age1 : forall k:knot,
age1 k =
match unsquash k with
| (O,_) => None
| (S n,x) => Some (squash (n,x))
end.