Skip to content

Commit 6395d69

Browse files
authored
feat: add HashMap.get*_filter* lemmas specialized for LawfulBEq (#8399)
This PR adds variants of `HashMap.getElem?_filter` that assume `LawfulBEq` and have a simpler right-hand-side. `simp` can already achieve these, via rewriting with `getKey_eq` under the lambda. However `grind` can not, and these lemmas help `grind` work with `HashMap` goals. There are variants for all variants of `HashMap`, `getElem?/getElem/getElem!/getD`, and for `filter` and `filterMap`.
1 parent 4ba72ae commit 6395d69

File tree

9 files changed

+307
-78
lines changed

9 files changed

+307
-78
lines changed

src/Lean/Expr.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ instance : Inhabited (FVarIdMap α) where
265265
/-- Universe metavariable Id -/
266266
structure MVarId where
267267
name : Name
268-
deriving Inhabited, BEq, Hashable, Repr
268+
deriving Inhabited, BEq, Hashable
269269

270270
instance : Repr MVarId where
271271
reprPrec n p := reprPrec n.name p

src/Std/Data/DHashMap/Lemmas.lean

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3430,13 +3430,13 @@ theorem get_filterMap [LawfulBEq α]
34303430
(isSome_apply_of_mem_filterMap h') :=
34313431
Raw₀.get_filterMap ⟨m.1, _⟩ m.2
34323432

3433-
@[grind =]
3433+
@[simp, grind =]
34343434
theorem get!_filterMap [LawfulBEq α]
34353435
{f : (a : α) → β a → Option (γ a)} {k : α} [Inhabited (γ k)] :
34363436
(m.filterMap f).get! k = ((m.get? k).bind (f k)).get! :=
34373437
Raw₀.get!_filterMap ⟨m.1, _⟩ m.2
34383438

3439-
@[grind =]
3439+
@[simp, grind =]
34403440
theorem getD_filterMap [LawfulBEq α]
34413441
{f : (a : α) → β a → Option (γ a)} {k : α} {fallback : γ k} :
34423442
(m.filterMap f).getD k fallback = ((m.get? k).bind (f k)).getD fallback :=
@@ -3502,13 +3502,20 @@ theorem size_filterMap_eq_size_iff [EquivBEq α] [LawfulHashable α]
35023502
(m.filterMap f).size = m.size ↔ ∀ k h, (f (m.getKey k h) (Const.get m k h)).isSome :=
35033503
Raw₀.Const.size_filterMap_eq_size_iff ⟨m.1, _⟩ m.2
35043504

3505-
@[grind =]
3505+
@[simp]
35063506
theorem get?_filterMap [EquivBEq α] [LawfulHashable α]
35073507
{f : α → β → Option γ} {k : α} :
35083508
Const.get? (m.filterMap f) k = (Const.get? m k).pbind (fun x h' =>
35093509
f (m.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x) :=
35103510
Raw₀.Const.get?_filterMap ⟨m.1, _⟩ m.2
35113511

3512+
/-- Simpler variant of `get?_filterMap` when `LawfulBEq` is available. -/
3513+
@[grind =]
3514+
theorem get?_filterMap' [LawfulBEq α] [LawfulHashable α]
3515+
{f : α → β → Option γ} {k : α} :
3516+
Const.get? (m.filterMap f) k = (Const.get? m k).bind fun x => f k x := by
3517+
simp [get?_filterMap]
3518+
35123519
theorem get?_filterMap_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α]
35133520
{f : α → β → Option γ} {k k' : α} (h : m.getKey? k = some k') :
35143521
Const.get? (m.filterMap f) k = (Const.get? m k).bind (f k') :=
@@ -3521,7 +3528,7 @@ theorem isSome_apply_of_mem_filterMap [EquivBEq α] [LawfulHashable α]
35213528
(Const.get m k (mem_of_mem_filterMap h))).isSome :=
35223529
Raw₀.Const.isSome_apply_of_contains_filterMap ⟨m.1, _⟩ m.2
35233530

3524-
@[simp, grind =]
3531+
@[simp]
35253532
theorem get_filterMap [EquivBEq α] [LawfulHashable α]
35263533
{f : α → β → Option γ} {k : α} {h} :
35273534
Const.get (m.filterMap f) k h =
@@ -3530,27 +3537,47 @@ theorem get_filterMap [EquivBEq α] [LawfulHashable α]
35303537
(isSome_apply_of_mem_filterMap h) :=
35313538
Raw₀.Const.get_filterMap ⟨m.1, _⟩ m.2
35323539

3540+
/-- Simpler variant of `get_filterMap` when `LawfulBEq` is available. -/
35333541
@[grind =]
3542+
theorem get_filterMap' [LawfulBEq α] [LawfulHashable α]
3543+
{f : α → β → Option γ} {k : α} {h} :
3544+
Const.get (m.filterMap f) k h =
3545+
(f k (Const.get m k (mem_of_mem_filterMap h))).get (by simpa using isSome_apply_of_mem_filterMap h) := by
3546+
simp [get_filterMap]
3547+
35343548
theorem get!_filterMap [EquivBEq α] [LawfulHashable α] [Inhabited γ]
35353549
{f : α → β → Option γ} {k : α} :
35363550
Const.get! (m.filterMap f) k =
35373551
((Const.get? m k).pbind (fun x h' =>
35383552
f (m.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).get! :=
35393553
Raw₀.Const.get!_filterMap ⟨m.1, _⟩ m.2
35403554

3555+
/-- Simpler variant of `get!_filterMap` when `LawfulBEq` is available. -/
3556+
@[grind =]
3557+
theorem get!_filterMap' [LawfulBEq α] [LawfulHashable α] [Inhabited γ]
3558+
{f : α → β → Option γ} {k : α} :
3559+
Const.get! (m.filterMap f) k = ((Const.get? m k).bind (f k) ).get!:= by
3560+
simp [get!_filterMap]
3561+
35413562
theorem get!_filterMap_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhabited γ]
35423563
{f : α → β → Option γ} {k k' : α} (h : m.getKey? k = some k') :
35433564
Const.get! (m.filterMap f) k = ((Const.get? m k).bind (f k')).get! :=
35443565
Raw₀.Const.get!_filterMap_of_getKey?_eq_some ⟨m.1, _⟩ m.2 h
35453566

3546-
@[grind =]
35473567
theorem getD_filterMap [EquivBEq α] [LawfulHashable α]
35483568
{f : α → β → Option γ} {k : α} {fallback : γ} :
35493569
Const.getD (m.filterMap f) k fallback =
35503570
((Const.get? m k).pbind (fun x h' =>
35513571
f (m.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback :=
35523572
Raw₀.Const.getD_filterMap ⟨m.1, _⟩ m.2
35533573

3574+
/-- Simpler variant of `getD_filterMap` when `LawfulBEq` is available. -/
3575+
@[grind =]
3576+
theorem getD_filterMap' [LawfulBEq α] [LawfulHashable α]
3577+
{f : α → β → Option γ} {k : α} {fallback : γ} :
3578+
Const.getD (m.filterMap f) k fallback = ((Const.get? m k).bind (f k)).getD fallback := by
3579+
simp [getD_filterMap]
3580+
35543581
theorem getD_filterMap_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α]
35553582
{f : α → β → Option γ} {k k' : α} {fallback : γ} (h : m.getKey? k = some k') :
35563583
Const.getD (m.filterMap f) k fallback = ((Const.get? m k).bind (f k')).getD fallback :=
@@ -3805,13 +3832,19 @@ theorem filter_equiv_self_iff [EquivBEq α] [LawfulHashable α]
38053832
fun h => (Raw₀.Const.filter_equiv_self_iff ⟨m.1, _⟩ m.2).mp h.1,
38063833
fun h => ⟨(Raw₀.Const.filter_equiv_self_iff ⟨m.1, _⟩ m.2).mpr h⟩ ⟩
38073834

3808-
@[grind =]
38093835
theorem get?_filter [EquivBEq α] [LawfulHashable α]
38103836
{f : α → β → Bool} {k : α} :
38113837
Const.get? (m.filter f) k = (Const.get? m k).pfilter (fun x h' =>
38123838
f (m.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x) :=
38133839
Raw₀.Const.get?_filter ⟨m.1, _⟩ m.2
38143840

3841+
/-- Simpler variant of `get?_filter` when `LawfulBEq` is available. -/
3842+
@[simp, grind =]
3843+
theorem get?_filter' [LawfulBEq α] [LawfulHashable α]
3844+
{f : α → β → Bool} {k : α} :
3845+
Const.get? (m.filter f) k = (Const.get? m k).filter (f k) := by
3846+
simp [get?_filter]
3847+
38153848
theorem get?_filter_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α]
38163849
{f : α → β → Bool} {k k' : α} :
38173850
m.getKey? k = some k' →
@@ -3824,27 +3857,39 @@ theorem get_filter [EquivBEq α] [LawfulHashable α]
38243857
Const.get (m.filter f) k h' = Const.get m k (mem_of_mem_filter h') :=
38253858
Raw₀.Const.get_filter ⟨m.1, _⟩ m.2
38263859

3827-
@[grind =]
38283860
theorem get!_filter [EquivBEq α] [LawfulHashable α] [Inhabited β]
38293861
{f : α → β → Bool} {k : α} :
38303862
Const.get! (m.filter f) k =
38313863
((Const.get? m k).pfilter (fun x h' =>
38323864
f (m.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).get! :=
38333865
Raw₀.Const.get!_filter ⟨m.1, _⟩ m.2
38343866

3867+
/-- Simpler variant of `get!_filter` when `LawfulBEq` is available. -/
3868+
@[grind =]
3869+
theorem get!_filter' [LawfulBEq α] [LawfulHashable α] [Inhabited β]
3870+
{f : α → β → Bool} {k : α} :
3871+
Const.get! (m.filter f) k = ((Const.get? m k).filter (f k)).get! := by
3872+
simp [get!_filter]
3873+
38353874
theorem get!_filter_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhabited β]
38363875
{f : α → β → Bool} {k k' : α} :
38373876
m.getKey? k = some k' →
38383877
Const.get! (m.filter f) k = ((Const.get? m k).filter (fun x => f k' x)).get! :=
38393878
Raw₀.Const.get!_filter_of_getKey?_eq_some ⟨m.1, _⟩ m.2
38403879

3841-
@[grind =]
38423880
theorem getD_filter [EquivBEq α] [LawfulHashable α]
38433881
{f : α → β → Bool} {k : α} {fallback : β} :
38443882
Const.getD (m.filter f) k fallback = ((Const.get? m k).pfilter (fun x h' =>
38453883
f (m.getKey k (mem_iff_isSome_get?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback :=
38463884
Raw₀.Const.getD_filter ⟨m.1, _⟩ m.2
38473885

3886+
/-- Simpler variant of `getD_filter` when `LawfulBEq` is available. -/
3887+
@[grind =]
3888+
theorem getD_filter' [LawfulBEq α] [LawfulHashable α]
3889+
{f : α → β → Bool} {k : α} {fallback : β} :
3890+
Const.getD (m.filter f) k fallback = ((Const.get? m k).filter (f k)).getD fallback := by
3891+
simp [getD_filter]
3892+
38483893
theorem getD_filter_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α]
38493894
{f : α → β → Bool} {k k' : α} {fallback : β} :
38503895
m.getKey? k = some k' →

src/Std/Data/DHashMap/RawLemmas.lean

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3702,13 +3702,19 @@ theorem size_filterMap_eq_size_iff [EquivBEq α] [LawfulHashable α]
37023702

37033703
-- TODO: `size_filterMap_le_size` is missing
37043704

3705-
@[grind =]
37063705
theorem get?_filterMap [EquivBEq α] [LawfulHashable α]
37073706
{f : α → β → Option γ} {k : α} (h : m.WF) :
37083707
Const.get? (m.filterMap f) k = (Const.get? m k).pbind (fun x h' =>
37093708
f (m.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x) := by
37103709
simp_to_raw using Raw₀.Const.get?_filterMap
37113710

3711+
/-- Simpler variant of `get?_filterMap` when `LawfulBEq` is available. -/
3712+
@[simp, grind =]
3713+
theorem get?_filterMap' [LawfulBEq α] [LawfulHashable α]
3714+
{f : α → β → Option γ} {k : α} (h : m.WF) :
3715+
Const.get? (m.filterMap f) k = (Const.get? m k).bind (f k) := by
3716+
simp [get?_filterMap, h]
3717+
37123718
theorem get?_filterMap_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α]
37133719
{f : α → β → Option γ} {k k' : α} (h : m.WF) :
37143720
m.getKey? k = some k' → Const.get? (m.filterMap f) k = (Const.get? m k).bind (f k') := by
@@ -3731,7 +3737,6 @@ theorem get_filterMap [EquivBEq α] [LawfulHashable α]
37313737
(isSome_apply_of_mem_filterMap h h') := by
37323738
simp_to_raw using Raw₀.Const.get_filterMap
37333739

3734-
@[grind =]
37353740
theorem get!_filterMap [EquivBEq α] [LawfulHashable α] [Inhabited γ]
37363741
{f : α → β → Option γ} {k : α} (h : m.WF) :
37373742
Const.get! (m.filterMap f) k =
@@ -3740,20 +3745,33 @@ theorem get!_filterMap [EquivBEq α] [LawfulHashable α] [Inhabited γ]
37403745
x)).get! := by
37413746
simp_to_raw using Raw₀.Const.get!_filterMap
37423747

3748+
/-- Simpler variant of `get!_filterMap` when `LawfulBEq` is available. -/
3749+
@[grind =]
3750+
theorem get!_filterMap' [LawfulBEq α] [LawfulHashable α] [Inhabited γ]
3751+
{f : α → β → Option γ} {k : α} (h : m.WF) :
3752+
Const.get! (m.filterMap f) k = ((Const.get? m k).bind (f k)).get! := by
3753+
simp [get!_filterMap, h]
3754+
37433755
theorem get!_filterMap_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhabited γ]
37443756
{f : α → β → Option γ} {k k' : α} (h : m.WF) :
37453757
m.getKey? k = some k' → Const.get! (m.filterMap f) k = ((Const.get? m k).bind
37463758
fun x => f k' x).get! := by
37473759
simp_to_raw using Raw₀.Const.get!_filterMap_of_getKey?_eq_some
37483760

3749-
@[grind =]
37503761
theorem getD_filterMap [EquivBEq α] [LawfulHashable α]
37513762
{f : α → β → Option γ} {k : α} {fallback : γ} (h : m.WF) :
37523763
Const.getD (m.filterMap f) k fallback =
37533764
((Const.get? m k).pbind (fun x h' =>
37543765
f (m.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := by
37553766
simp_to_raw using Raw₀.Const.getD_filterMap
37563767

3768+
/-- Simpler variant of `getD_filterMap` when `LawfulBEq` is available. -/
3769+
@[grind =]
3770+
theorem getD_filterMap' [LawfulBEq α] [LawfulHashable α]
3771+
{f : α → β → Option γ} {k : α} {fallback : γ} (h : m.WF) :
3772+
Const.getD (m.filterMap f) k fallback = ((Const.get? m k).bind (f k)).getD fallback := by
3773+
simp [getD_filterMap, h]
3774+
37573775
theorem getD_filterMap_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α]
37583776
{f : α → β → Option γ} {k k' : α} {fallback : γ} (h : m.WF) :
37593777
m.getKey? k = some k' → Const.getD (m.filterMap f) k fallback = ((Const.get? m k).bind
@@ -4028,13 +4046,20 @@ theorem filter_equiv_self_iff [EquivBEq α] [LawfulHashable α]
40284046
simp [← contains_iff_mem]
40294047
simp_to_raw using Raw₀.Const.filter_equiv_self_iff
40304048

4031-
@[grind =]
4049+
@[simp]
40324050
theorem get?_filter [EquivBEq α] [LawfulHashable α]
40334051
{f : α → β → Bool} {k : α} (h : m.WF) :
40344052
Const.get? (m.filter f) k = (Const.get? m k).pfilter (fun x h' =>
40354053
f (m.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x) := by
40364054
simp_to_raw using Raw₀.Const.get?_filter
40374055

4056+
/-- Simpler variant of `get?_filter` when `LawfulBEq` is available. -/
4057+
@[grind =]
4058+
theorem get?_filter' [LawfulBEq α] [LawfulHashable α]
4059+
{f : α → β → Bool} {k : α} (h : m.WF) :
4060+
Const.get? (m.filter f) k = (Const.get? m k).filter (f k) := by
4061+
simp [get?_filter, h]
4062+
40384063
theorem get?_filter_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α]
40394064
{f : α → β → Bool} {k k' : α} (h : m.WF) :
40404065
m.getKey? k = some k' →
@@ -4047,27 +4072,39 @@ theorem get_filter [EquivBEq α] [LawfulHashable α]
40474072
Const.get (m.filter f) k h' = Const.get m k (mem_of_mem_filter h h') := by
40484073
simp_to_raw using Raw₀.Const.get_filter
40494074

4050-
@[grind =]
40514075
theorem get!_filter [EquivBEq α] [LawfulHashable α] [Inhabited β]
40524076
{f : α → β → Bool} {k : α} (h : m.WF) :
40534077
Const.get! (m.filter f) k =
40544078
((Const.get? m k).pfilter (fun x h' =>
40554079
f (m.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).get! := by
40564080
simp_to_raw using Raw₀.Const.get!_filter
40574081

4082+
/-- Simpler variant of `get!_filter` when `LawfulBEq` is available. -/
4083+
@[grind =]
4084+
theorem get!_filter' [LawfulBEq α] [LawfulHashable α] [Inhabited β]
4085+
{f : α → β → Bool} {k : α} (h : m.WF) :
4086+
Const.get! (m.filter f) k = ((Const.get? m k).filter (f k)).get! := by
4087+
simp [get!_filter, h]
4088+
40584089
theorem get!_filter_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhabited β]
40594090
{f : α → β → Bool} {k k' : α} (h : m.WF) :
40604091
m.getKey? k = some k' →
40614092
Const.get! (m.filter f) k = ((Const.get? m k).filter (fun x => f k' x)).get! := by
40624093
simp_to_raw using Raw₀.Const.get!_filter_of_getKey?_eq_some
40634094

4064-
@[grind =]
40654095
theorem getD_filter [EquivBEq α] [LawfulHashable α]
40664096
{f : α → β → Bool} {k : α} {fallback : β} (h : m.WF) :
40674097
Const.getD (m.filter f) k fallback = ((Const.get? m k).pfilter (fun x h' =>
40684098
f (m.getKey k ((mem_iff_isSome_get? h).mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := by
40694099
simp_to_raw using Raw₀.Const.getD_filter
40704100

4101+
/-- Simpler variant of `getD_filter` when `LawfulBEq` is available. -/
4102+
@[grind =]
4103+
theorem getD_filter' [LawfulBEq α] [LawfulHashable α]
4104+
{f : α → β → Bool} {k : α} {fallback : β} (h : m.WF) :
4105+
Const.getD (m.filter f) k fallback = ((Const.get? m k).filter (f k)).getD fallback := by
4106+
simp [getD_filter, h]
4107+
40714108
theorem getD_filter_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α]
40724109
{f : α → β → Bool} {k k' : α} {fallback : β} (h : m.WF) :
40734110
m.getKey? k = some k' →

0 commit comments

Comments
 (0)