Definition prop {A: Type}  (P: Prop) : pred A := (fun _  => P).
Hint Unfold prop.
Definition TT {A}: pred A := prop True.
Definition FF  {A}: pred A := prop False.
Set Implicit Arguments.
Definition imp {A}  (P Q:pred A) :=
fun a:A => P a -> Q a.
Definition orp {A} (P Q:pred A) :=
fun a:A => P a \/ Q a.
Definition andp {A} (P Q:pred A) :=
fun a:A => P a /\ Q a.
Definition allp {A B: Type} (f: B -> pred A) : pred A
:= fun a => forall b, f b a.
Definition exp {A B: Type} (f: B -> pred A) : pred A
:= fun a => exists b, f b a.
Notation "'emp'" := identity.
Definition sepcon {A} {JA: Join A}(p q:pred A) := fun z:A =>
exists x:A, exists y:A, join x y z /\ p x /\ q y.
Definition wand {A}  {JA: Join A}  (p q:pred A) := fun y =>
forall x z, join x y z -> p x -> q z.
Notation "P '|--' Q" := (derives P Q) (at level 80, no associativity).
Notation "'EX'  x ':' T ',' P " := (exp (fun x:T => P%pred)) (at level 65, x at level 99) : pred.
Notation "'ALL'  x ':' T  ',' P " := (allp (fun x:T => P%pred)) (at level 65, x at level 99) : pred.
Infix "||" := orp (at level 50, left associativity) : pred.
Infix "&&" := andp (at level 40, left associativity) : pred.
Notation "P '-->' Q" := (imp P Q) (at level 55, right associativity) : pred.
Notation "P '<-->' Q" := (andp (imp P Q) (imp Q P)) (at level 57, no associativity) : pred.
Notation "P '*' Q" := (sepcon P Q) : pred.
Notation "P '-*' Q" := (wand P Q) (at level 60, right associativity) : pred.
Notation "'!!' e" := (prop e) (at level 25) : pred.
Definition precise {A}  {JA: Join A}{PA: Perm_alg A}  (P: pred A) : Prop :=
forall w w1 w2, P w1 -> P w2 -> join_sub w1 w -> join_sub w2 w -> w1=w2.
Definition precise2  {A} {JA: Join A}{PA: Perm_alg A}  (P: pred A) : Prop :=
forall Q R, P * (Q && R) = (P * Q) && (P * R).

(* Specifications: *)
Lemma precise_eq {A}  {JA: Join A}{PA: Perm_alg A}{SA: Sep_alg A}{CA: Canc_alg A}:
precise =
fun P : pred A => forall Q R, P * (Q && R) = (P * Q) && (P * R).
Lemma derives_precise {A} {JA: Join A}{PA: Perm_alg A}:
forall P Q, (P |-- Q) -> precise Q -> precise P.
Lemma prop_true_and:
forall (P: Prop) A (Q: pred A), P -> (!! P && Q = Q).
Lemma prop_andp_e {A}:  forall P Q (w:A), (!! P && Q) w -> P /\ Q w.
Lemma prop_andp_i {A}:  forall P Q (w:A), P /\ Q w -> (!! P && Q) w.
Lemma derives_trans {A}:  forall (P Q R: pred A), P |-- Q -> Q |-- R -> P |-- R.
Lemma and_i {A}: forall (P Q R: pred A),
P |-- Q -> P |-- R -> P |-- Q && R.
Lemma andp_derives {A}  :
forall P Q P' Q': pred A, P |-- P' -> Q |-- Q' -> P && Q |-- P' && Q'.
Lemma sepcon_assoc {A} {JA: Join A}{PA: Perm_alg A}:
forall p q r, (((p * q) * r) = (p * (q * r))).
Lemma sepcon_comm {A} {JA: Join A}{PA: Perm_alg A}:  forall (P Q: pred A) , P * Q = Q * P.
Lemma sepcon_emp {A} {JA: Join A}{PA: Perm_alg A}{SA: Sep_alg A}: forall P, (P * emp) = P.
Lemma emp_sepcon {A} {JA: Join A}{PA: Perm_alg A}{SA: Sep_alg A}:
forall P, (emp*P) = P.