Set Implicit Arguments.
Inductive fold_rel (A: Type) (f: A -> A -> A -> Prop):  A -> list A -> A -> Prop :=
| fold_rel_nil: forall w, fold_rel f w nil w
| fold_rel_cons: forall a l w w1 w2,
f w a w1 ->
fold_rel f w1 l w2 ->
fold_rel f w (a::l) w2.
Inductive list_forall2 {A B} (P: A -> B -> Prop): list A -> list B -> Prop :=
| list_forall2_nil:
list_forall2 P nil nil
| list_forall2_cons:
forall a1 al b1 bl,
P a1 b1 ->
list_forall2 P al bl ->
list_forall2 P (a1 :: al) (b1 :: bl).
Fixpoint replace (A: Type) (l: list A) (n:nat) (new: A) {struct n} : option (list A) :=
match (l, n) with
| (nil, n) => None
| (x :: xs, O) => Some (new :: xs)
| (x :: xs, S n) =>
match (replace xs n new) with
|  None => None
|  Some xs => Some (x :: xs)
end
end.
Definition list_join {A} {JA: Join A}: A -> list A -> A -> Prop :=
fold_rel join.
Definition age1_list {A} `{ageable A} := list_forall2 age.
(*****************************)

Lemma ageN_join2 {A}  {JA: Join A}{PA: Perm_alg A}{agA: ageable A}{AgeA: Age_alg A}:
forall n (w1 w2 w3 w3': A),
join w1 w2 w3 ->
ageN n w3 = Some w3' ->
exists w1', exists w2',
ageN n w1 = Some w1' /\ ageN n w2 = Some w2' /\ join w1' w2' w3'.