Commit 42e3e6de authored by Robbert Krebbers's avatar Robbert Krebbers

Improve and document split_and tactics.

parent 1f72cb6b
...@@ -476,7 +476,7 @@ Lemma insert_subset_inv {A} (m1 m2 : M A) i x : ...@@ -476,7 +476,7 @@ Lemma insert_subset_inv {A} (m1 m2 : M A) i x :
m1 !! i = None <[i:=x]> m1 m2 m1 !! i = None <[i:=x]> m1 m2
m2', m2 = <[i:=x]>m2' m1 m2' m2' !! i = None. m2', m2 = <[i:=x]>m2' m1 m2' m2' !! i = None.
Proof. Proof.
intros Hi Hm1m2. exists (delete i m2). split_ands. intros Hi Hm1m2. exists (delete i m2). split_and?.
- rewrite insert_delete. done. eapply lookup_weaken, strict_include; eauto. - rewrite insert_delete. done. eapply lookup_weaken, strict_include; eauto.
by rewrite lookup_insert. by rewrite lookup_insert.
- eauto using insert_delete_subset. - eauto using insert_delete_subset.
......
...@@ -220,7 +220,7 @@ Proof. done. Qed. ...@@ -220,7 +220,7 @@ Proof. done. Qed.
Program Instance sum_finite `{Finite A, Finite B} : Finite (A + B)%type := Program Instance sum_finite `{Finite A, Finite B} : Finite (A + B)%type :=
{| enum := (inl <$> enum A) ++ (inr <$> enum B) |}. {| enum := (inl <$> enum A) ++ (inr <$> enum B) |}.
Next Obligation. Next Obligation.
intros. apply NoDup_app; split_ands. intros. apply NoDup_app; split_and?.
- apply (NoDup_fmap_2 _). by apply NoDup_enum. - apply (NoDup_fmap_2 _). by apply NoDup_enum.
- intro. rewrite !elem_of_list_fmap. intros (?&?&?) (?&?&?); congruence. - intro. rewrite !elem_of_list_fmap. intros (?&?&?) (?&?&?); congruence.
- apply (NoDup_fmap_2 _). by apply NoDup_enum. - apply (NoDup_fmap_2 _). by apply NoDup_enum.
...@@ -237,7 +237,7 @@ Program Instance prod_finite `{Finite A, Finite B} : Finite (A * B)%type := ...@@ -237,7 +237,7 @@ Program Instance prod_finite `{Finite A, Finite B} : Finite (A * B)%type :=
Next Obligation. Next Obligation.
intros ??????. induction (NoDup_enum A) as [|x xs Hx Hxs IH]; simpl. intros ??????. induction (NoDup_enum A) as [|x xs Hx Hxs IH]; simpl.
{ constructor. } { constructor. }
apply NoDup_app; split_ands. apply NoDup_app; split_and?.
- by apply (NoDup_fmap_2 _), NoDup_enum. - by apply (NoDup_fmap_2 _), NoDup_enum.
- intros [? y]. rewrite elem_of_list_fmap. intros (?&?&?); simplify_eq. - intros [? y]. rewrite elem_of_list_fmap. intros (?&?&?); simplify_eq.
clear IH. induction Hxs as [|x' xs ?? IH]; simpl. clear IH. induction Hxs as [|x' xs ?? IH]; simpl.
...@@ -271,7 +271,7 @@ Next Obligation. ...@@ -271,7 +271,7 @@ Next Obligation.
intros ????. induction n as [|n IH]; simpl; [apply NoDup_singleton |]. intros ????. induction n as [|n IH]; simpl; [apply NoDup_singleton |].
revert IH. generalize (list_enum (enum A) n). intros l Hl. revert IH. generalize (list_enum (enum A) n). intros l Hl.
induction (NoDup_enum A) as [|x xs Hx Hxs IH]; simpl; auto; [constructor |]. induction (NoDup_enum A) as [|x xs Hx Hxs IH]; simpl; auto; [constructor |].
apply NoDup_app; split_ands. apply NoDup_app; split_and?.
- by apply (NoDup_fmap_2 _). - by apply (NoDup_fmap_2 _).
- intros [k1 Hk1]. clear Hxs IH. rewrite elem_of_list_fmap. - intros [k1 Hk1]. clear Hxs IH. rewrite elem_of_list_fmap.
intros ([k2 Hk2]&?&?) Hxk2; simplify_eq/=. destruct Hx. revert Hxk2. intros ([k2 Hk2]&?&?) Hxk2; simplify_eq/=. destruct Hx. revert Hxk2.
......
...@@ -85,7 +85,7 @@ Proof. ...@@ -85,7 +85,7 @@ Proof.
rewrite elem_of_list_intersection in Hx; naive_solver. } rewrite elem_of_list_intersection in Hx; naive_solver. }
intros [(l&?&?) (k&?&?)]. assert (x list_intersection l k) intros [(l&?&?) (k&?&?)]. assert (x list_intersection l k)
by (by rewrite elem_of_list_intersection). by (by rewrite elem_of_list_intersection).
exists (list_intersection l k); split; [exists l, k|]; split_ands; auto. exists (list_intersection l k); split; [exists l, k|]; split_and?; auto.
by rewrite option_guard_True by eauto using elem_of_not_nil. by rewrite option_guard_True by eauto using elem_of_not_nil.
- unfold elem_of, hashset_elem_of, intersection, hashset_intersection. - unfold elem_of, hashset_elem_of, intersection, hashset_intersection.
intros [m1 ?] [m2 ?] x; simpl. intros [m1 ?] [m2 ?] x; simpl.
...@@ -95,7 +95,7 @@ Proof. ...@@ -95,7 +95,7 @@ Proof.
intros [(l&?&?) Hm2]; destruct (m2 !! hash x) as [k|] eqn:?; eauto. intros [(l&?&?) Hm2]; destruct (m2 !! hash x) as [k|] eqn:?; eauto.
destruct (decide (x k)); [destruct Hm2; eauto|]. destruct (decide (x k)); [destruct Hm2; eauto|].
assert (x list_difference l k) by (by rewrite elem_of_list_difference). assert (x list_difference l k) by (by rewrite elem_of_list_difference).
exists (list_difference l k); split; [right; exists l,k|]; split_ands; auto. exists (list_difference l k); split; [right; exists l,k|]; split_and?; auto.
by rewrite option_guard_True by eauto using elem_of_not_nil. by rewrite option_guard_True by eauto using elem_of_not_nil.
- unfold elem_of at 2, hashset_elem_of, elements, hashset_elems. - unfold elem_of at 2, hashset_elem_of, elements, hashset_elems.
intros [m Hm] x; simpl. setoid_rewrite elem_of_list_bind. split. intros [m Hm] x; simpl. setoid_rewrite elem_of_list_bind. split.
...@@ -107,7 +107,7 @@ Proof. ...@@ -107,7 +107,7 @@ Proof.
rewrite map_Forall_to_list in Hm. generalize (NoDup_fst_map_to_list m). rewrite map_Forall_to_list in Hm. generalize (NoDup_fst_map_to_list m).
induction Hm as [|[n l] m' [??]]; induction Hm as [|[n l] m' [??]];
csimpl; inversion_clear 1 as [|?? Hn]; [constructor|]. csimpl; inversion_clear 1 as [|?? Hn]; [constructor|].
apply NoDup_app; split_ands; eauto. apply NoDup_app; split_and?; eauto.
setoid_rewrite elem_of_list_bind; intros x ? ([n' l']&?&?); simpl in *. setoid_rewrite elem_of_list_bind; intros x ? ([n' l']&?&?); simpl in *.
assert (hash x = n hash x = n') as [??]; subst. assert (hash x = n hash x = n') as [??]; subst.
{ split; [eapply (Forall_forall (λ x, hash x = n) l); eauto|]. { split; [eapply (Forall_forall (λ x, hash x = n) l); eauto|].
......
...@@ -57,7 +57,7 @@ Proof. ...@@ -57,7 +57,7 @@ Proof.
{ intros -> Hlen; edestruct help; rewrite Hlen; simpl; lia. } { intros -> Hlen; edestruct help; rewrite Hlen; simpl; lia. }
{ intros <- Hlen; edestruct help; rewrite <-Hlen; simpl; lia. } { intros <- Hlen; edestruct help; rewrite <-Hlen; simpl; lia. }
intros Hs Hlen; apply IH in Hs; destruct Hs; intros Hs Hlen; apply IH in Hs; destruct Hs;
simplify_eq/=; split_ands'; auto using N.div_lt_upper_bound with lia. simplify_eq/=; split_and?; auto using N.div_lt_upper_bound with lia.
rewrite (N.div_mod x 10), (N.div_mod y 10) by done. rewrite (N.div_mod x 10), (N.div_mod y 10) by done.
auto using N.mod_lt with f_equal. auto using N.mod_lt with f_equal.
Qed. Qed.
......
...@@ -54,11 +54,20 @@ Ltac done := ...@@ -54,11 +54,20 @@ Ltac done :=
Tactic Notation "by" tactic(tac) := Tactic Notation "by" tactic(tac) :=
tac; done. tac; done.
(** Whereas the [split] tactic splits any inductive with one constructor, the (** Tactics for splitting conjunctions:
tactic [split_and] only splits a conjunction. *)
Ltac split_and := match goal with |- _ _ => split end. - [split_and] : split the goal if is syntactically of the shape [_ ∧ _]
Ltac split_ands := repeat split_and. - [split_ands?] : split the goal repeatedly (perhaps zero times) while it is
Ltac split_ands' := repeat (hnf; split_and). of the shape [_ ∧ _].
- [split_ands!] : works similarly, but at least one split should succeed. In
order to do so, it will head normalize the goal first to possibly expose a
conjunction.
Note that [split_and] differs from [split] by only splitting conjunctions. The
[split] tactic splits any inductive with one constructor. *)
Tactic Notation "split_and" := match goal with |- _ _ => split end.
Tactic Notation "split_and" "?" := repeat split_and.
Tactic Notation "split_and" "!" := hnf; split_and; split_and?.
(** The tactic [case_match] destructs an arbitrary match in the conclusion or (** The tactic [case_match] destructs an arbitrary match in the conclusion or
assumptions, and generates a corresponding equality. This tactic is best used assumptions, and generates a corresponding equality. This tactic is best used
......
...@@ -64,7 +64,7 @@ Proof. ...@@ -64,7 +64,7 @@ Proof.
- intros ? [o t t']; unfold map_to_list; simpl. - intros ? [o t t']; unfold map_to_list; simpl.
assert (NoDup ((prod_map Z.pos id <$> map_to_list t) ++ assert (NoDup ((prod_map Z.pos id <$> map_to_list t) ++
prod_map Z.neg id <$> map_to_list t')). prod_map Z.neg id <$> map_to_list t')).
{ apply NoDup_app; split_ands. { apply NoDup_app; split_and?.
- apply (NoDup_fmap_2 _), NoDup_map_to_list. - apply (NoDup_fmap_2 _), NoDup_map_to_list.
- intro. rewrite !elem_of_list_fmap. naive_solver. - intro. rewrite !elem_of_list_fmap. naive_solver.
- apply (NoDup_fmap_2 _), NoDup_map_to_list. } - apply (NoDup_fmap_2 _), NoDup_map_to_list. }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment