(* * Copyright (c) 2009-2011, Andrew Appel, Robert Dockins and Aquinas Hobor. * *)
(** The cross split axiom looks unwieldly, but here we show that it arises naturally as a kind of distributivity property. Cross split can be rendered, with some accuracy, as "the separation algebra is distributive." *)
(** This definition mirrors the definition of distributivity in a join-semilattice.  This definition generalizes the standard notion of distributivity in a lattice, but only mentions of the lattice operators.  Here we transplant the semilattice definition into the setting of separation algebras. *)
Definition sa_distributive (A: Type) {JOIN: Join A} :=
forall a b x z,
join a b z ->
constructive_join_sub x z ->
{a' : A & {b' : A &
(constructive_join_sub a' a * constructive_join_sub b' b * join a' b' x)%type}}.
(* (** We define this weaker version of cross-split in order to show that the sa_distributive axiom is equivalent. The ordinary cross_split is more constructive (it uses a sigma type rather than 'exists'), so we have to weaken it to show the correspondence.  We could, instead, define and use a constructive version of join_sub. *)
Definition weak_cross_split `{sepalg A} :=
forall a b c d z : A,
join a b z ->
join c d z ->
exists x:(A*A*A*A), match x with (ac,ad,bc,bd) =>
join ac ad a /\
join bc bd b /\
join ac bc c /\
join ad bd d
end.
*)
(** NOTICE ABOUT REDUNDANT LEMMAS: Since sa_distribute <-> cross_split, many of the proofs below are redundant. This was part of an experiment to see whether, in general, sa_distributive is simpler to prove than cross_split.  Short answer:  not really. *)
Instance cross_split_fun: forall A (JOIN: Join A) (key: Type),
Cross_alg A -> Cross_alg (key -> A).
Instance Cross_prod : forall A B saA saB,
@Cross_alg A saA ->
@Cross_alg B saB ->
@Cross_alg (A * B) (Join_prod _ saA _ saB).

Lemma constructive_join_sub_smash {A} {JA: Join A}{PA: Perm_alg A}{SA: Sep_alg A}{CA: Disj_alg A}:
(forall x:A, {identity x}+{~identity x}) ->
forall a c : lifted JA,
constructive_join_sub (proj1_sig a) (proj1_sig c) ->
@constructive_join_sub (option (lifted JA)) _ (Some a) (Some c).