(* * Copyright (c) 2009-2010, Andrew Appel, Robert Dockins and Aquinas Hobor. * *)
Declare Scope pred.
Delimit Scope pred with pred.
Local Open Scope pred.
(* A "pre-predicate" is hereditary iff whenever it is true at world a, it is also true at all worlds accessable from a via R. *)
Definition hereditary {A} (R:A->A->Prop) (p:A->Prop) :=
forall a a':A, R a a' -> p a -> p a'.
(* A predicate is a hereditary pre-predicate *)
Definition pred (A:Type) {AG:ageable A} :=
{ p:A -> Prop | hereditary age p }.
Bind Scope pred with pred.
(* Here is some junk that makes the definition of "pred" opaque to most tactics but still allows the "Program" extension to see it is a subset type.  The coercion is sugar that allows us to use predicates easily. *)
Definition app_pred {A} `{ageable A} (p:pred A) : A -> Prop := proj1_sig p.
Definition pred_hereditary `{ageable} (p:pred A) := proj2_sig p.
Coercion app_pred : pred >-> Funclass.
Global Opaque pred.
Hint Resolve @pred_hereditary : core.

Lemma nec_hereditary {A} `{ageable A} (p: A -> Prop) : hereditary age p ->
forall a a':A, necR a a' -> p a -> p a'.