Skip to content

feat: Add Array.scan{l,r,lM,rM}#1589

Merged
fgdorais merged 73 commits intoleanprover-community:mainfrom
cmlsharp:scan-array
Feb 13, 2026
Merged

feat: Add Array.scan{l,r,lM,rM}#1589
fgdorais merged 73 commits intoleanprover-community:mainfrom
cmlsharp:scan-array

Conversation

@cmlsharp
Copy link
Copy Markdown
Contributor

@cmlsharp cmlsharp commented Dec 31, 2025

This PR adds the Array equivalents of List.scan{l,r,L,R}. It was originally part of #1581.

  • This PR provides both reference and efficient versions of Array.scanlM and Array.scanrM, and then defines Array.scanl and Array.scanr in terms of them. This is identical to how the standard library currently handles Array.fold*.
  • Unlike the standard library, this PR attempts to make minimal use of unsafe in the implementations of the efficient versions. It defines an assumption (as Array.size_fits_usize) as well as an unsafe proof of this assumption (as Array.unsafe_size_fits_usize). These are currently public definitions. I could make them private, but they seem useful for writing other 'efficient' array functions.
  • Array.scanlM is proven to be equivalent to its efficient implementation under the assumption that Array.size_fits_usize holds. The efficient version of Array.scanrM additionally uses this assumption when constructing the proofs for the bounds checks.
  • I do not have a proof that the efficient version of Array.scanrM is equivalent to its efficient version under Array.size_fits_usize. It should be possible, but the structure of these two implementations differ more, so the proof is more difficult. With Array.scanlM the only difference between the implementations was the use of USize or Nat for the index, whereas the Array.scanrM reference implementation builds the array, then reverses it and the efficient implementation iterates over the array in reverse.

@github-actions github-actions bot added the awaiting-review This PR is ready for review; the author thinks it is ready to be merged. label Dec 31, 2025
@cmlsharp
Copy link
Copy Markdown
Contributor Author

cmlsharp commented Jan 5, 2026

WIP

@github-actions github-actions bot added WIP work in progress and removed awaiting-review This PR is ready for review; the author thinks it is ready to be merged. labels Jan 5, 2026
@ghost ghost added the merge-conflict This PR has merge conflicts with the `main` branch which must be resolved by the author. label Jan 6, 2026
@cmlsharp
Copy link
Copy Markdown
Contributor Author

cmlsharp commented Jan 7, 2026

awaiting-review

@github-actions github-actions bot added awaiting-review This PR is ready for review; the author thinks it is ready to be merged. and removed WIP work in progress labels Jan 7, 2026
(a.eraseIdxIfInBounds i).size = if i < a.size then a.size-1 else a.size := by
grind

theorem toList_drop (as: Array α) (n : Nat) :
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
theorem toList_drop (as: Array α) (n : Nat) :
@[simp, grind =]
theorem toList_drop (as: Array α) (n : Nat) :

to match toList_erase above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work as a simp lemma because simp simplifies '(as.drop n).toList' to 'List.take (as.size - n) (List.drop n as.toList)`

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fwiw I think this is very frustrating. Array.drop is automatically simplified to Array.extract. This over-eager simplification is why I wanted a toList_drop method to begin with.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are way too many simp lemmas for my taste. Eric is very fond of them though and I respect his opinion. We (in general, including Eric and I) need a common language to talk about simp-normal-form. The Mathlib/Batteries concerns are a bit different.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for starting the Zulip thread; indeed this can't be simp right now.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we resolve this or are we hoping to fix the simp issues upstream?

Comment on lines +331 to +337
theorem toArray_scanl {f : β → α → β} {as : List α} :
(as.scanl f init).toArray = as.toArray.scanl f init := by
rw [← Array.toList_scanl]

theorem toArray_scanr {f : α → β → β} {as : List α} :
(as.scanr f init).toArray = as.toArray.scanr f init := by
rw [← Array.toList_scanr]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to claim that these should be simp, but having found #lean4 > Direction of List.map_toArray vs Array.toList_map @ 💬 I'm no longer sure.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we proceed without these simps?

@fgdorais
Copy link
Copy Markdown
Collaborator

Our Mathlib Testing CI is partly broken at this time. The last run has reported an error: https://github.com/leanprover-community/mathlib4-nightly-testing/tree/batteries-pr-testing-1589

Could you investigate to see whether there needs to be a Mathlib adaptation or whether this is a false negative?

@cmlsharp
Copy link
Copy Markdown
Contributor Author

leanprover-community/mathlib4#35228

I opened a PR that fixes the issue. The problem was that I added List.reverse_singleton, but that was something that already existed in mathlib. The simple solution is to replace it.

@fgdorais
Copy link
Copy Markdown
Collaborator

Thanks! This is not the preferred way to make a Mathlib adaptation PR but I think we can work with it.

The preferred way is to edit the Mathlib Testing branch until CI works and then make a PR from that branch into Mathlib. I've added your fix to that branch and we will see what CI says, in case we need to add some additional fixes. If CI clears, then we can just use your Mathlib PR, otherwise we will revert to the preferred route.

@kim-em Could you give @cmlsharp write access to Mathlib Testing. (Is there a way to automate this?)

@cmlsharp
Copy link
Copy Markdown
Contributor Author

Oh sorry about that! I will do that in the future. I just realized there was a commit I meant to push prior to making the PR (marking this lemma simp since it is marked that way in mathlib). I just pushed it.

@fgdorais fgdorais added this pull request to the merge queue Feb 13, 2026
Merged via the queue into leanprover-community:main with commit 414003c Feb 13, 2026
1 check passed
@github-actions github-actions bot removed the awaiting-review This PR is ready for review; the author thinks it is ready to be merged. label Feb 13, 2026
mathlib-bors bot pushed a commit to leanprover-community/mathlib4 that referenced this pull request Feb 13, 2026
After [batteries#1589](leanprover-community/batteries#1589) is merged:

- [x] Merge leanprover-community/mathlib4:master
- [x] Edit the lakefile to point to leanprover-community/batteries:main
- [x] Run lake update batteries
- [ ] Wait for CI and merge

Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com>
Co-authored-by: F. G. Dorais <fgdorais@gmail.com>
rao107 pushed a commit to rao107/mathlib4 that referenced this pull request Feb 18, 2026
After [batteries#1589](leanprover-community/batteries#1589) is merged:

- [x] Merge leanprover-community/mathlib4:master
- [x] Edit the lakefile to point to leanprover-community/batteries:main
- [x] Run lake update batteries
- [ ] Wait for CI and merge

Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com>
Co-authored-by: F. G. Dorais <fgdorais@gmail.com>
Maldooor pushed a commit to Maldooor/mathlib4 that referenced this pull request Feb 25, 2026
After [batteries#1589](leanprover-community/batteries#1589) is merged:

- [x] Merge leanprover-community/mathlib4:master
- [x] Edit the lakefile to point to leanprover-community/batteries:main
- [x] Run lake update batteries
- [ ] Wait for CI and merge

Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com>
Co-authored-by: F. G. Dorais <fgdorais@gmail.com>
fgdorais added a commit that referenced this pull request Feb 26, 2026
Co-authored-by: François G. Dorais <fgdorais@gmail.com>
Co-authored-by: Kim Morrison <477956+kim-em@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Gavin Zhao <gavinzhaojw@protonmail.com>
Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com>
Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
pfaffelh pushed a commit to pfaffelh/mathlib4 that referenced this pull request Mar 2, 2026
After [batteries#1589](leanprover-community/batteries#1589) is merged:

- [x] Merge leanprover-community/mathlib4:master
- [x] Edit the lakefile to point to leanprover-community/batteries:main
- [x] Run lake update batteries
- [ ] Wait for CI and merge

Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com>
Co-authored-by: F. G. Dorais <fgdorais@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

builds-mathlib will-merge-soon PR will be merged soon. Any concerns should be raised quickly.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants