Proof using.
induction l; simpl; intros.
- intuition.
- intuition.
+ repeat break_match; simpl; auto.
do_bool.
find_apply_lem_hyp has_key_true_elim. break_and. repeat find_rewrite.
assert (n < snd k) by auto. omega.
+ repeat break_match; simpl.
* { destruct (has_key (fst k) (snd k) a) eqn:?; auto.
right. intuition. apply IHl; auto.
do_bool.
intros. destruct (clientId_eq_dec (eClient a) (fst k)).
- repeat find_rewrite. rewrite get_set_same in *. find_inversion.
repeat match goal with
| H : context [ has_key (fst k')] |- _ => clear H
end.
find_apply_lem_hyp has_key_false_elim.
intuition; try congruence.
assert (has_key (fst k) (eId a) a = true) by eauto using has_key_intro'.
assert (eId a <= snd k) by auto.
omega.
- rewrite get_set_diff in * by auto. auto.
}
* do_bool. apply IHl; auto. intros.
{ destruct (has_key (fst k) (snd k) a) eqn:?; auto.
find_apply_lem_hyp has_key_true_elim. break_and.
repeat find_rewrite. assert (n < snd k) by auto. omega.
}
* { destruct (has_key (fst k) (snd k) a) eqn:?; auto.
right. intuition. apply IHl; auto.
do_bool.
intros. destruct (clientId_eq_dec (eClient a) (fst k)).
- repeat find_rewrite. rewrite get_set_same in *. find_inversion.
repeat match goal with
| H : context [ has_key (fst k')] |- _ => clear H
end.
find_apply_lem_hyp has_key_false_elim.
intuition; try congruence.
assert (has_key (fst k) (eId a) a = true) by eauto using has_key_intro'.
assert (eId a <= snd k) by auto.
omega.
- rewrite get_set_diff in * by auto. auto.
}
Qed.

Lemma before_func_deduplicate :
forall k k' l,
before_func (has_key (fst k) (snd k)) (has_key (fst k') (snd k')) l ->
(forall id',
before_func (has_key (fst k) id') (has_key (fst k) (snd k)) l ->
id' <= snd k) ->
before_func (has_key (fst k) (snd k)) (has_key (fst k') (snd k')) (deduplicate_log l).