diff --git a/theories/prelude/gmap.v b/theories/prelude/gmap.v index ea79b8c63517d442620a6a6eac811650e20dcab4..2daddef4aa726b58a035c1e41738e06e2f1f90a0 100644 --- a/theories/prelude/gmap.v +++ b/theories/prelude/gmap.v @@ -123,6 +123,56 @@ Next Obligation. by rewrite map_of_to_list. Qed. +(** * Curry and uncurry *) +Definition gmap_curry `{Countable K1, Countable K2} {A} : + gmap K1 (gmap K2 A) → gmap (K1 * K2) A := + map_fold (λ i1 m' macc, + map_fold (λ i2 x, <[(i1,i2):=x]>) macc m') ∅. +Definition gmap_uncurry `{Countable K1, Countable K2} {A} : + gmap (K1 * K2) A → gmap K1 (gmap K2 A) := + map_fold (λ '(i1,i2) x, + partial_alter (Some ∘ <[i2:=x]> ∘ from_option id ∅) i1) ∅. + +Section curry_uncurry. + Context `{Countable K1, Countable K2} {A : Type}. + + Lemma lookup_gmap_curry (m : gmap K1 (gmap K2 A)) i j : + gmap_curry m !! (i,j) = m !! i ≫= (!! j). + Proof. + apply (map_fold_ind (λ mr m, mr !! (i,j) = m !! i ≫= (!! j))). + { by rewrite !lookup_empty. } + clear m; intros i' m2 m m12 Hi' IH. + apply (map_fold_ind (λ m2r m2, m2r !! (i,j) = <[i':=m2]> m !! i ≫= (!! j))). + { rewrite IH. destruct (decide (i' = i)) as [->|]. + - rewrite lookup_insert, Hi'; simpl; by rewrite lookup_empty. + - by rewrite lookup_insert_ne by done. } + intros j' y m2' m12' Hj' IH'. destruct (decide (i = i')) as [->|]. + - rewrite lookup_insert; simpl. destruct (decide (j = j')) as [->|]. + + by rewrite !lookup_insert. + + by rewrite !lookup_insert_ne, IH', lookup_insert by congruence. + - by rewrite !lookup_insert_ne, IH', lookup_insert_ne by congruence. + Qed. + + Lemma lookup_gmap_uncurry (m : gmap (K1 * K2) A) i j : + gmap_uncurry m !! i ≫= (!! j) = m !! (i, j). + Proof. + apply (map_fold_ind (λ mr m, mr !! i ≫= (!! j) = m !! (i, j))). + { by rewrite !lookup_empty. } + clear m; intros [i' j'] x m12 mr Hij' IH. + destruct (decide (i = i')) as [->|]. + - rewrite lookup_partial_alter. destruct (decide (j = j')) as [->|]. + + destruct (mr !! i'); simpl; by rewrite !lookup_insert. + + destruct (mr !! i'); simpl; by rewrite !lookup_insert_ne by congruence. + - by rewrite lookup_partial_alter_ne, lookup_insert_ne by congruence. + Qed. + + Lemma gmap_curry_uncurry (m : gmap (K1 * K2) A) : + gmap_curry (gmap_uncurry m) = m. + Proof. + apply map_eq; intros [i j]. by rewrite lookup_gmap_curry, lookup_gmap_uncurry. + Qed. +End curry_uncurry. + (** * Finite sets *) Notation gset K := (mapset (gmap K)). Instance gset_dom `{Countable K} {A} : Dom (gmap K A) (gset K) := mapset_dom.