(* * 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).
(* Warning: This lemma is valid, but it's not clear that it's useful *)
Definition opposite_bij {A B} (b: bijection A B) : bijection B A :=
Bijection _ _ (bij_g _ _ b) (bij_f _ _ b) (bij_gf _ _ b) (bij_fg _ _ b).

Lemma Cross_bij' : forall A B JA JB bij,
@Cross_alg B JB ->
JB =  (Join_bij A JA B bij) ->
@Cross_alg A  JA.