Set Implicit Arguments.
Definition sepcon_unique1 {X A} `{SepLog A} (P: X -> A): Prop :=
forall x, P x * P x |-- FF.
Definition sepcon_unique2 {X Y A} `{SepLog A} (P: X -> Y -> A): Prop :=
forall x y1 y2, P x y1 * P x y2 |-- FF.
Section IterSepCon.
Context {A : Type}.
Context {B : Type}.
Context {ND : NatDed A}.
Context {SL : SepLog A}.
Context {ClS: ClassicalSep A}.
Context {CoSL: CorableSepLog A}.
Section SingleSepPred.
Context (p : B -> A).
Fixpoint iter_sepcon (l : list B) : A :=
match l with
| nil => emp
| x :: xl => p x * iter_sepcon xl
end.

(* Specifications: *)
Lemma iter_sepcon_app:
forall (l1 l2 : list B), iter_sepcon (l1 ++ l2) = iter_sepcon l1 * iter_sepcon l2.
Lemma iter_sepcon_app_comm: forall (l1 l2 : list B), iter_sepcon (l1 ++ l2) = iter_sepcon (l2 ++ l1).
Lemma iter_sepcon_in_true: forall (l : list B) x, In x l -> iter_sepcon l |-- p x * TT.
Lemma iter_sepcon_incl_true: forall (l s: list B),
NoDup s -> incl s l -> iter_sepcon l |-- iter_sepcon s * TT.
Lemma iter_sepcon_unique_nodup: forall (l : list B), sepcon_unique1 p -> iter_sepcon l |-- !!(NoDup l).
Lemma iter_sepcon_emp': forall (l : list B), (forall x, In x l -> p x = emp) -> iter_sepcon l = emp.
Lemma iter_sepcon_emp: forall (l l' : list B), (forall x, p x |-- emp) -> NoDup l' -> incl l' l -> iter_sepcon l |-- iter_sepcon l'.
Lemma iter_sepcon_nil: iter_sepcon nil = emp.
Instance iter_sepcon_permutation_proper : Proper ((pointwise_relation B eq) ==> (@Permutation B) ==> eq) iter_sepcon.