feat: Add @[spec] lemmas for forIn at Std.PRange (#9848)

This PR adds `@[spec]` lemmas for `forIn` and `forIn'` at `Std.PRange`.
This commit is contained in:
Sebastian Graf 2025-08-11 16:34:34 +02:00 committed by GitHub
parent 5b5bb5174b
commit 264e451d3c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -8,6 +8,7 @@ module
prelude
public import Std.Do.Triple.Basic
public import Std.Do.WP
import Init.Data.Range.Polymorphic
@[expose] public section
@ -481,6 +482,46 @@ theorem Spec.forIn_range {β : Type} {m : Type → Type v} {ps : PostShape}
simp only [Std.Range.forIn_eq_forIn_range', Std.Range.size]
apply Spec.forIn_list inv step
open Std.PRange in
@[spec]
theorem Spec.forIn'_prange {α β : Type u}
[Monad m] [WPMonad m ps]
[UpwardEnumerable α]
[SupportsUpperBound su α] [SupportsLowerBound sl α] [HasFiniteRanges su α]
[BoundedUpwardEnumerable sl α] [LawfulUpwardEnumerable α]
[LawfulUpwardEnumerableLowerBound sl α] [LawfulUpwardEnumerableUpperBound su α]
{xs : PRange ⟨sl, su⟩ α} {init : β} {f : (a : α) → a ∈ xs → β → m (ForInStep β)}
(inv : Invariant xs.toList β ps)
(step : ∀ b rpref x (hx : x ∈ xs) suff (h : xs.toList = rpref.reverse ++ x :: suff),
⦃inv.1 (⟨rpref, x::suff, by simp [h]⟩, b)}
f x hx b
⦃(fun r => match r with
| .yield b' => inv.1 (⟨x::rpref, suff, by simp [h]⟩, b')
| .done b' => inv.1 (⟨xs.toList.reverse, [], by simp⟩, b'), inv.2)}) :
⦃inv.1 (⟨[], xs.toList, by simp⟩, init)} forIn' xs init f ⦃(fun b => inv.1 (⟨xs.toList.reverse, [], by simp⟩, b), inv.2)} := by
simp only [forIn'_eq_forIn'_toList]
apply Spec.forIn'_list inv (fun b rpref x hx suff h => step b rpref x (mem_toList_iff_mem.mp hx) suff h)
open Std.PRange in
@[spec]
theorem Spec.forIn_prange {α β : Type u}
[Monad m] [WPMonad m ps]
[UpwardEnumerable α]
[SupportsUpperBound su α] [SupportsLowerBound sl α] [HasFiniteRanges su α]
[BoundedUpwardEnumerable sl α] [LawfulUpwardEnumerable α]
[LawfulUpwardEnumerableLowerBound sl α] [LawfulUpwardEnumerableUpperBound su α]
{xs : PRange ⟨sl, su⟩ α} {init : β} {f : α → β → m (ForInStep β)}
(inv : Invariant xs.toList β ps)
(step : ∀ b rpref x suff (h : xs.toList = rpref.reverse ++ x :: suff),
⦃inv.1 (⟨rpref, x::suff, by simp [h]⟩, b)}
f x b
⦃(fun r => match r with
| .yield b' => inv.1 (⟨x::rpref, suff, by simp [h]⟩, b')
| .done b' => inv.1 (⟨xs.toList.reverse, [], by simp⟩, b'), inv.2)}) :
⦃inv.1 (⟨[], xs.toList, by simp⟩, init)} forIn xs init f ⦃(fun b => inv.1 (⟨xs.toList.reverse, [], by simp⟩, b), inv.2)} := by
simp only [forIn]
apply Spec.forIn'_prange inv (fun b rpref x _hx suff h => step b rpref x suff h)
@[spec]
theorem Spec.forIn'_array {α β : Type u}
[Monad m] [WPMonad m ps]