Definition reduction_ok (k: kind) (a: expr) (m: mem) (rd: reduction) : Prop :=
  match k, rd with
  | LV, Lred _ l' m' => lred ge e a m l' m'
  | RV, Rred _ r' m' t => rred ge a m t r' m' /\ exists w', possible_trace w t w'
  | RV, Callred _ fd args tyres m' => callred ge a m fd args tyres /\ m' = m
  | LV, Stuckred => ~imm_safe_t k a m
  | RV, Stuckred => ~imm_safe_t k a m
  | _, _ => False
  end.Definition reducts_ok (k: kind) (a: expr) (m: mem) (ll: reducts expr) : Prop :=
  (forall C rd,
      In (C, rd) ll ->
      exists a', exists k', context k' k C /\ a = C a' /\ reduction_ok k' a' m rd)
  /\ (ll = nil -> match k with LV => is_loc a <> None | RV => is_val a <> None end).Definition list_reducts_ok (al: exprlist) (m: mem) (ll: reducts exprlist) : Prop :=
  (forall C rd,
      In (C, rd) ll ->
      exists a', exists k', contextlist k' C /\ al = C a' /\ reduction_ok k' a' m rd)
  /\ (ll = nil -> is_val_list al <> None).Ltac monadInv :=
  match goal with
  | [ H: match ?x with Some _ => _ | None => None end = Some ?y |- _ ] =>
      destruct x eqn:?; [monadInv|discriminate]
  | [ H: match ?x with left _ => _ | right _ => None end = Some ?y |- _ ] =>
      destruct x; [monadInv|discriminate]
  | _ => idtac
  end.

Lemma incontext2_ok: forall k a m k1 a1 res1 k2 a2 res2 C1 C2, reducts_ok k1 a1 m res1 -> reducts_ok k2 a2 m res2 -> a = C1 a1 -> a = C2 a2 -> context k1 k C1 -> context k2 k C2 -> match k1 with LV => is_loc a1 = None | RV => is_val a1 = None end \/ match k2 with LV => is_loc a2 = None | RV => is_val a2 = None end -> reducts_ok k a m (incontext2 C1 res1 C2 res2).