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).

Lemma and_i {A}: forall (P Q R: pred A),
P |-- Q -> P |-- R -> P |-- Q && R.