Instance Join_prop : Join (sig P) :=
                 fun x y z: (sig P) => join (proj1_sig x) (proj1_sig y) (proj1_sig z).Instance Perm_prop : Perm_alg (sig P).Instance Sep_prop (SA: Sep_alg A)(HPcore : forall x, P x -> P (core x)): Sep_alg (sig P).Instance Sing_prop  (SA: Sep_alg A)(Sing_A: Sing_alg A)
               (HPcore : forall x, P x -> P (core x)): P the_unit ->
    @Sing_alg (sig P) Join_prop (Sep_prop _ HPcore).Instance Canc_prop  {CA: Canc_alg A}:  Canc_alg (sig P).Instance Disj_prop {DA: Disj_alg A}: Disj_alg (sig P).Instance Join_fun: Join (key -> t') :=
                  fun a b c : key -> t' => forall x, join (a x) (b x) (c x).Instance Perm_fun : Perm_alg (key -> t').Instance Sep_fun (SA: Sep_alg t'): Sep_alg (key -> t').Instance Sing_fun (SA: Sep_alg t'): Sing_alg t' -> Sing_alg (key -> t').Instance Canc_fun: Canc_alg t' -> Canc_alg (key -> t').Instance Disj_fun: Disj_alg t' -> Disj_alg (key -> t').Instance Join_pi: Join P := fun x y z => forall i:I, join (x i) (y i) (z i).Instance Perm_pi  : Perm_alg P.Instance Sep_pi (SA : forall i:I, Sep_alg (Pi i)): Sep_alg P.Instance Canc_pi: (forall i, Canc_alg (Pi i)) -> Canc_alg P.Instance Disj_pi: (forall i, Disj_alg (Pi i)) -> Disj_alg P.Inductive join_sigma : S -> S -> S -> Prop :=
    j_sig_def : forall (i:I) (a b c:Sigma i),
      join a b c ->
      join_sigma (existT Sigma i a) (existT Sigma i b) (existT Sigma i c).Inductive join_sigma : S -> S -> S -> Prop :=
    j_sig_def : forall (i:I) (a b c:Sigma i),
      join a b c ->
      join_sigma (existT Sigma i a) (existT Sigma i b) (existT Sigma i c).Instance Join_sigma: Join S := join_sigma.Instance Perm_sigma: Perm_alg S.Instance Sep_sigma (SA : forall i:I, Sep_alg (Sigma i)) : Sep_alg S.Instance Canc_sigma: (forall i, Canc_alg (Sigma i)) -> Canc_alg S.Instance Disj_sigma: (forall i, Disj_alg (Sigma i)) -> Disj_alg S.Instance Join_prod : Join (A*B) :=
               fun (x y z:A*B) =>  join (fst x) (fst y) (fst z) /\ join (snd x) (snd y) (snd z).Instance Perm_prod  : Perm_alg (A*B).Instance Sep_prod (SAa: Sep_alg A) (SAb: Sep_alg B) : Sep_alg (A*B).Instance Sing_prod {SAa: Sep_alg A} {SAb: Sep_alg B} {SingA: Sing_alg A}{SingB: Sing_alg B}: Sing_alg (A*B).Instance Canc_prod {CAa: Canc_alg A} {CAb:  Canc_alg B}: Canc_alg (A*B).Instance Disj_prod {DAa: Disj_alg A} {DAb:  Disj_alg B}: Disj_alg (A*B).Instance Join_sum : Join (A+B) :=
    (fun (x y z: A+B) =>
    match x, y, z with
    | inl xa, inl ya, inl za => join xa ya za
    | inr xb, inr yb, inr zb => join xb yb zb
    | _, _, _ => False
    end).Instance Perm_sum: Perm_alg (A+B).Instance Sep_sum (SAa: Sep_alg A) (SAb: Sep_alg B): Sep_alg (A+B).Instance Canc_sum {CAa: Canc_alg A} {CAb:  Canc_alg B}: Canc_alg (A+B).Instance Disj_sum {DAa: Disj_alg A} {DAb:  Disj_alg B}: Disj_alg (A+B).Inductive list_join : list A -> list A -> list A -> Prop :=
  | lj_nil : list_join nil nil nil
  | lj_cons : forall x y z xs ys zs,
      join x y z ->
      list_join xs ys zs ->
      list_join (x::xs) (y::ys) (z::zs).Inductive list_join : list A -> list A -> list A -> Prop :=
  | lj_nil : list_join nil nil nil
  | lj_cons : forall x y z xs ys zs,
      join x y z ->
      list_join xs ys zs ->
      list_join (x::xs) (y::ys) (z::zs).Inductive list_join : list A -> list A -> list A -> Prop :=
  | lj_nil : list_join nil nil nil
  | lj_cons : forall x y z xs ys zs,
      join x y z ->
      list_join xs ys zs ->
      list_join (x::xs) (y::ys) (z::zs).Instance Join_list: Join (list A) := list_join.Instance Perm_list: Perm_alg (list A).Instance Sep_list (SAa: Sep_alg A) : Sep_alg (list A).Instance Canc_list {CA: Canc_alg A}: Canc_alg (list A).Instance Disj_list {DAa: Disj_alg A} : Disj_alg (list A).(** A join homomorphism is a function from one separation
    algebra to another which preserves the join relation.

    This is used when we build the sa_preimage (to add a Perm_alg to the knot).
 *)

Definition raw_join_hom A B (j1: A -> A -> A -> Prop) (j2: B -> B -> B -> Prop) (f:A ->B) :=
  forall x y z,
    j1 x y z ->
    j2 (f x) (f y) (f z).Definition join_hom {A} {JA: Join A} {B} {JB: Join B} (f:A ->B) :=
  forall x y z,
    join x y z ->
    join (f x) (f y) (f z).

(* Specifications: *)
Lemma f_inj : forall x y : A, f x = f y -> x = y.