Section CombineJoin.
Variable A : Type.
Variable JA: Join A.
Variable pa_A : Perm_alg A.
Variable sa_A : Sep_alg A.
Variable ca_A : Canc_alg A.
Variable da_A : Disj_alg A.
(* We either need an explicit top witness or some kind of axiom of choice (if not here, then in sa_fun or somesuch).  It is a little ugly this way but I don't see any other way around. Aquinas *)
Variable A_top : A.
Variable A_top_full : full A_top.
Variable T1 : Type.
Variable T2 : Type.
Variable J1: Join T1.
Variable pa_T1: Perm_alg T1.
Variable sa_T1: Sep_alg T1.
Variable combjoin : T1 -> T1 -> T2 -> Prop.
Variable combjoin_eq : forall v1 v1' v2 v2',
combjoin v1 v1' v2 ->
combjoin v1 v1' v2' ->
v2 = v2'.
Variable combjoin_assoc : forall v1 v2 v3 v4 v5,
join v1 v2 v3 ->
combjoin v3 v4 v5 ->
{v' : T1 & join v2 v4 v' /\ combjoin v1 v' v5}.
Variable combjoin_com : forall v1 v2 v3,
combjoin v1 v2 v3 ->
combjoin v2 v1 v3.
Variable combjoin_canc : forall v1 v1' v2 v3,
combjoin v1 v2 v3 ->
combjoin v1' v2 v3 ->
v1 = v1'.
(* We would really prefer this to be: exists top, join (projT1 j1) (projT1 j2) top /\ full top but, again, we run into Type/Prop problems and wind up needing some form of the axiom of choice somewhere or other. *)
Definition covers (j1 j2 : ijoinable A) : Prop :=
join (projT1 j1) (projT1 j2) A_top.
Inductive combiner : Type :=
| CEmpty
| CPart : forall (sh : ijoinable A) (v : T1), combiner
| CFull : forall (v : T2), combiner.
Instance Join_combiner : Join combiner :=
fun c1 c2 c3 =>
match (c1,c2,c3) with
| (CEmpty, CEmpty, CEmpty) => True
| (CEmpty, CPart a v, CPart a' v') => a = a' /\ v = v'
| (CPart a v, CEmpty, CPart a' v')  => a = a' /\ v = v'
| (CEmpty, CFull v, CFull v') => v = v'
| (CFull v, CEmpty, CFull v') => v = v'
| (CPart a v, CPart a' v', CPart a'' v'') => ijoin a a' a'' /\ join v v' v''
| (CPart a v, CPart a' v', CFull v'') => combjoin v v' v'' /\ covers a a'
| _ => False
end.
Proof with auto.
intros.
icase x;icase y;icase z;icase z';try inversion H;try inversion H0;try congruence.
f_equal.
eapply ijoin_eq; eauto.
eapply join_eq; eauto.
elimtype False; clear - pa_A sa_A H1 H4 A_top_full.
destruct sh; destruct sh0; destruct sh1.
red in H1; red in H4; simpl in H4.
generalize (join_eq H1 H4); intro; subst x1.
unfold midObj in *.
tauto.
elimtype False; clear - pa_A sa_A H2 H3 A_top_full.
destruct sh;destruct sh0;destruct sh1.
red in H3; red in H2; simpl in H2.
generalize (join_eq H2 H3);intro;subst x1.
unfold midObj in *.
tauto.
rewrite (combjoin_eq _ _ _ _ H1 H3)...
Qed.

Lemma combineJ_assoc: forall a b c d e : combiner,
join a b d -> join d c e ->
{f : combiner & join b c f /\ join a f e}.