Compare commits

..

328 Commits

Author SHA1 Message Date
Kim Morrison
ffe0692471 feat: generalize Process.output/run to allow an input 2025-07-25 19:29:53 +10:00
Sebastian Ullrich
671057eecf fix: unif_hint under the module system (#9530) 2025-07-25 09:05:31 +00:00
Kim Morrison
0ab69a32cb chore: parameterize NoNatZeroDivisors by NatModule instead of HMul (#9527)
This PR changes `Lean.Grind.NoNatZeroDivisors` so that it is
parametrised by a `NatModule` instance rather than just a `HMul`
instance. This is sufficiently general for our purposes, and is a
band-aid (~40% improvement) for the performance problems we've been
seeing coming from inference here. The problems observed in Mathlib may
not see much improvement, however.
2025-07-25 08:46:05 +00:00
Joachim Breitner
6995f280b4 fix: unfold abstracted proofs before processing recursion (#9191)
This PR lets the equation compiler unfold abstracted proofs again if
they would otherwise hide recursive calls.
    
This fixes #8939.

---------

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2025-07-25 08:00:57 +00:00
Kim Morrison
73422d52fd chore: remove simp from unindexable Array.filterMap_some_fun (#9521) 2025-07-25 06:22:42 +00:00
Mac Malone
4875c6447f fix: lake: import all transitivity & related bugs (#9525)
This PR fixes Lake's handling of a module system `import all`.
Previously, Lake treated `import all` the same a non-module `import`,
importing all private data in the transitive import tree. Lake now
distinguishes the two, with `import all M` just importing the private
data of `M`. The direct private imports of `M` are followed, but they
are not promoted.

This also fixes some other Lake bugs with module system imports that
were discovered in the process.
2025-07-25 05:56:38 +00:00
Cameron Zwarich
820c1e6f15 chore: remove tests that recompile builtin definitions (#9523)
In the early days of the new compiler, it was common to make tests that
manually compiled a definition with the new compiler. The arity
reduction pass in LCNF deliberately does not compute a fixed point to
find a minimal set of used parameters for performance reasons, but
running it a second time can lead to different decisions being made and
a decl arity mismatch. This has been an issue for multiple people during
development. Removing the tests fixes the problem.

Fixes #9186.
2025-07-25 04:37:33 +00:00
Leonardo de Moura
92b870da4a fix: kernel deep recursion with normalizer (#9522)
This PR uses `withAbstractAtoms` to prevent the kernel from accidentally
reducing the atoms in the arith normlizer while typechecking. This PR
also sets `implicitDefEqProofs := false` in the `grind` normalizer
2025-07-25 04:37:17 +00:00
Kim Morrison
3eaa44dd4d fix: definition of Lean.Grind.Field (#9520)
This PR corrects the changes to `Lean.Grind.Field` made in #9500. 

(The lack of examples of fields in the core repository is a problem! I
guess it is likely that for interval arithmetic we will at least need
`Rat` soon.)
2025-07-25 00:35:43 +00:00
Rob23oba
e148871087 chore: fix spelling errors (#9175)
(Almost) only typos in constant names and doc-strings were considered;
grammar was not considered. Also, along others,
`mkDefinitionValInferrringUnsafe` has been fixed :-)
2025-07-24 23:35:32 +00:00
Henrik Böving
75b5c8b0aa perf: phashmap benchmark (#9517)
This PR adds a benchmark for the persistent hashmap, in particular also
covering the non
linear insert case which is often hit in practical uses. Furthermore the
same test case is also
added to the treemap benchmark.
2025-07-24 14:57:07 +00:00
Sebastian Ullrich
4177f123bc fix: expose LCNF of private inline decl referenced by implemented_by (#9514) 2025-07-24 13:05:21 +00:00
Sebastian Ullrich
db292b4c82 chore: minimize benchmark imports so we don't spend a majority in importing (#9513) 2025-07-24 12:14:12 +00:00
Henrik Böving
9669c6d5f1 perf: add benchmark for congruence reasoning in simp (#9511)
This PR adds a benchmark for putting pressure on simp's congruence
abilities.
2025-07-24 10:47:37 +00:00
Sebastian Graf
2748633637 fix: Make mframe, mspec and mvcgen hygienic (#9512)
This PR makes `mframe`, `mspec` and `mvcgen` respect hygiene.
Inaccessible stateful hypotheses can now be named with a new tactic
`mrename_i` that works analogously to `rename_i`.
2025-07-24 10:30:16 +00:00
Joachim Breitner
2075103cd9 fix: show kernel diagnostics even for examples (#9509)
This PR surfaces kernel diagnostics even in `example`.

The problem was that the kernel checking happens asynchronously. We
cannot use `reportDiag` in `addDecl`, which spawns that task, due to the
module hierarchy. For non `example`-declaration, `reportDiag` is called
somewhere else later, but for `example`, the `withoutModifyingEnv` in
`elabMutualDef` hid the kernel diagnostics. (But only the kernel
diagnostics; they are in the `Environment`, while the others are in the
`State`).

I also observed that the `reportDiag` in `elabAsync` (but not in
`elabSync`) duplicated the reporting, so without `elab.Async true` you
get the message twice. To fix this, `reportDiag` now resets the
diagnostics. This should avoid reporting counts twice in general (at
least within a linear use of the state).

---------

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2025-07-24 09:21:47 +00:00
Sebastian Graf
b7dfda4f45 chore: Extract collectFreshMVars from withCollectingNewGoalsFrom (#9502) 2025-07-24 07:44:06 +00:00
Sebastian Graf
45514a955e feat: Add missing simp lemmas to mleave (#9506)
This PR adds a few missing simp lemmas to `mleave`.
2025-07-24 07:12:32 +00:00
Sebastian Graf
4fdf74500d fix: Remove duplicate syntax definitions for mvcgen* (#9505)
This PR removes vestigial syntax definitions in
`Lean.Elab.Tactic.Do.VCGen` that when imported undefine the `mvcgen`
tactic. Now it should be possible to import Mathlib and still use
`mvcgen`.
2025-07-24 06:57:00 +00:00
Sebastian Graf
d8f9463af3 feat: Add *.by_wp adequacy theorems for ReaderM and ExceptM (#9504)
This PR adds a few more `*.by_wp` "adequacy theorems" that allows to
prove facts about programs in `ReaderM` and `ExceptM` using the `Std.Do`
framework.
2025-07-24 06:53:59 +00:00
Sebastian Graf
ab18c82371 chore: Remove unused definitions relating to PredTrans (#9503) 2025-07-24 06:50:57 +00:00
Kim Morrison
68adcdb475 chore: maintain failing grind tests about Nat as a semiring (#9501)
These tests (still failing until we embed a NatModule in its IntModule
envelope) had further broken because of name changes.
2025-07-24 06:44:39 +00:00
Kim Morrison
3cde12567f feat: add HPow Int field to Field (#9500)
This PR adds a `HPow \a Int \a` field to `Lean.Grind.Field`, and
sufficient axioms to connect it to the operations, so that in future we
can reason about exponents in `grind`. To avoid collisions, we also move
the `HPow \a Nat \a` field in `Semiring` from the extends clause to a
field. Finally, we add some failing tests about normalizing exponents.
2025-07-24 06:00:11 +00:00
Kim Morrison
8d5da6491a chore: remove provable fields from Grind.Nat/IntModule (#9499) 2025-07-24 05:23:35 +00:00
Kim Morrison
eea7e50519 chore: script/release_steps.py only merges nightly-testing on rc1 (#9498) 2025-07-24 04:31:11 +00:00
Lean stage0 autoupdater
c4c3497776 chore: update stage0 2025-07-24 01:57:24 +00:00
Kyle Miller
d45cc674ea feat: make cdot expansion take hygiene into account (#9443)
This PR makes cdot function expansion take hygiene information into
account, fixing "parenthesis capturing" errors that can make erroneous
cdots trigger cdot expansion in conjunction with macros. For example,
given
```lean
macro "baz% " t:term : term => `(1 + ($t))
```
it used to be that `baz% ·` would expand to `1 + fun x => x`, but now
the parentheses in `($t)` do not capture the cdot. We also fix an
oversight where cdot function expansion ignored the fact that type
ascriptions and tuples were supposed to delimit expansion, and also now
the quotation prechecker ignores the identifier in `hygieneInfo`. (#9491
added the hygiene information to the parenthesis and cdot syntaxes.)

This fixes a bug discovered by [Google
DeepMind](https://storage.googleapis.com/deepmind-media/DeepMind.com/Blog/imo-2024-solutions/P1/index.html),
which made use of `useλy . x=>y.rec λS p=>?_`. The `use` tactic from
Mathlib wrapped the provided term in a type ascription, and so this was
equivalent to `use fun x => λy x x=>y.rec λS p=>?_`. (Note that cdot
function expansion is not able to take into account *where* the cdots
are located, and it is syntactically valid to insert an identifier into
the binder list like this. If we ever want to address this in the
future, we could have cdots expand into a special term that wraps an
identifier that evaluates to a local, but which would cause errors in
other contexts.)

Design note: we put the `hygieneInfo` on the open parenthesis rather
than at the end, since that way the hygiene information is available
even when there are parsing errors. This is important since we rely on
being able to elaborate partial syntax to get elab info (e.g. in `(a.`
to get completion info). Note that syntax matchers check that the
`hygieneInfo` is actually present, so such partial syntax would not be
matched.
2025-07-24 00:43:32 +00:00
Cameron Zwarich
8a0d036e82 perf: use an FVarIdHashSet for ReduceArity.State.used (#9497) 2025-07-24 00:25:26 +00:00
Lean stage0 autoupdater
9d93b10919 chore: update stage0 2025-07-23 21:41:23 +00:00
Kyle Miller
2412d52536 feat: add hygiene info to paren/tuple/typeAscription syntaxes (#9491)
This PR adds hygiene info to paren/tuple/typeAscription syntaxes, which
will be used to implement hygienic cdot function expansion in #9443.
2025-07-23 20:57:06 +00:00
Kyle Miller
e686d040ea fix: add missing spaces for pretty printing (#9475)
This PR fixes the way some syntaxes are pretty printed due to missing
whitespace advice.

Removes a vestigal `have'` tactic macro introduced in
0032578d5b back when `let` syntax looked
like `let Type := v`.

While we're here, extends the `let`/`have` docstrings to mention `(eq :=
h)` syntax.

Whitespace issues were reported by Damiano Testa [on
Zulip](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Some.20pretty.20printing.20quirks/near/529964215).
2025-07-23 19:35:04 +00:00
Leonardo de Moura
2dce18655d fix: incorrect proof term in grind linarith (#9487)
This PR fixes an incorrect proof term constructed by `grind linarith`,
as reported in #9485.

closes #9485
2025-07-23 17:34:44 +00:00
Kyle Miller
6cf22b32aa feat: custom structure constructors can update binder kinds of parameters (#9480)
This PR adds a feature where `structure` constructors can override the
inferred binder kinds of the type's parameters. In the following, the
`(p)` binder on `toLp` causes `p` to be an explicit parameter to
`WithLp.toLp`:
```lean
structure WithLp (p : Nat) (V : Type) where toLp (p) ::
  ofLp : V
```
This reflects the syntax of the feature added in #7742 for overriding
binder kinds of structure projections. Similarly, only those parameters
in the header of the `structure` may be updated; it is an error to try
to update binder kinds of parameters included via `variable`.

Closes #9072.

Fixes a possible bug from stale caches when creating the type of the
constructor.
2025-07-23 16:33:34 +00:00
Rob23oba
d24219697e feat: unexpand Vector.mk #[...] _ to #v[...] (#8391)
This PR adds an unexpander for `Vector.mk` that unexpands `Vector.mk
#[...] _` to `#v[...]`.
```lean
-- previously:
#check #v[1, 2, 3] -- { toArray := #[1, 2, 3], size_toArray := ⋯ } : Vector Nat 3
-- now:
#check #v[1, 2, 3] -- #v[1, 2, 3] : Vector Nat 3
```

---------

Co-authored-by: Kyle Miller <kmill31415@gmail.com>
2025-07-23 16:27:51 +00:00
Lean stage0 autoupdater
d353a25a36 chore: update stage0 2025-07-23 16:53:11 +00:00
Sebastian Ullrich
9dc4dbebe1 perf: do not try to mmap .ir to the same address as .olean (#9488) 2025-07-23 16:12:44 +00:00
Sebastian Ullrich
04be1c6b5c chore: CI: cached Lake as secondary job (#9486) 2025-07-23 13:26:35 +00:00
Sebastian Ullrich
e46a3108d9 perf: do not export specializations (#9465)
Trading an insignificant amount of IR bloat for better recompilation
avoidance
2025-07-23 13:12:15 +00:00
Sebastian Ullrich
4cbfa485fa chore: fix test on macOS (#9483) 2025-07-23 12:10:13 +00:00
Sebastian Ullrich
9328271dd0 perf: do not export LCNF decls of closed terms (#9484)
This was only necessary when `isDeclMeta` and `isDeclPublic` were
intertwined
2025-07-23 09:50:29 +00:00
Lean stage0 autoupdater
f137d43931 chore: update stage0 2025-07-23 09:39:13 +00:00
Sebastian Ullrich
0ba5413266 refactor: remove unused Environment.extraConstNames (#9470)
Obsoleted in #9356
2025-07-23 08:58:32 +00:00
Sebastian Ullrich
fefc033515 chore: disable artifacts cache for building stage2+ (#9482) 2025-07-23 08:44:08 +00:00
Lean stage0 autoupdater
d888039468 chore: update stage0 2025-07-23 08:54:57 +00:00
Sebastian Ullrich
ddc4cf0a97 refactor: private field use in Meta.Context (#9468)
This PR resolves an issue where the `Meta.Context.configKey` field is
private but we still want to use the constructor of the structure for
setting other fields, which would be prevented by the module system
checks:
```lean
structure Context where
  private config    : Config               := {}
  private configKey : UInt64               := config.toKey
...

def ContextInfo.runMetaM (info : ContextInfo) (lctx : LocalContext) (x : MetaM α) : IO α := do
  -- cannot call private constructor of `Meta.Context`!
  (·.1) <$> info.runCoreM (x.run { lctx := lctx } { mctx := info.mctx })
```
Instead, the private field is extracted into an (existing) structure
that applies its default value:
```lean
/-- Configuration with key produced by `Config.toKey`. -/
structure ConfigWithKey where
  private mk ::
  config : Config := {}
  key    : UInt64 := config.toKey
  
structure Context where
  keyedConfig : ConfigWithKey := default
```
Thus `Context`'s constructor remains public without exposing a way to
set `key` directly.
2025-07-23 08:16:44 +00:00
Leonardo de Moura
aa5b392e35 fix: canonicalization of non-standard OfNat.ofNat terms (#9481)
This PR fixes a kernel type mismatch that occurs when using `grind` on
goals containing non-standard `OfNat.ofNat` terms. For example, in issue
#9477, the `0` in the theorem `range_lower` has the form:
```lean
(@OfNat.ofNat
  (Std.PRange.Bound (Std.PRange.RangeShape.lower (Std.PRange.RangeShape.mk Std.PRange.BoundShape.closed Std.PRange.BoundShape.open)) Nat)
  (nat_lit 0)
  (instOfNatNat (nat_lit 0)))
```
instead of the more standard form:
```lean
(@OfNat.ofNat
  Nat
  (nat_lit 0)
  (instOfNatNat (nat_lit 0)))
```

Closes #9477
2025-07-23 04:10:21 +00:00
Lean stage0 autoupdater
6346fdb253 chore: update stage0 2025-07-23 02:31:29 +00:00
Leonardo de Moura
7d2a7dba81 fix: improve evalInt? (#9479)
This PR improves the `evalInt?` function, which is used to evaluate
configuration parameters from the `ToInt` type class. This PR also adds
a new `evalNat?` function for handling the `IsCharP` type class, and
introduces a configuration option:
```
grind (exp := <num>)
```
This option controls the maximum exponent size considered during
expression evaluation. Previously, `evalInt?` used `whnf`, which could
run out of stack space when reducing terms such as `2^1024`.

closes #9427
2025-07-23 01:51:04 +00:00
Aaron Liu
98f05c47d0 fix: add binrel% macros for notation in Init.Core (#9084)
This PR adds `binrel%` macros for `!=` and `≠` notation defined in
`Init.Core`. This allows the elaborator to insert coercions on both
sides of the relation, instead of committing to the type on the left
hand side.

I first discovered this bug while working on Brouwer's fixed point
theorem. See the discussion on Zulip at [#lean4 > Elaboration of
&#96;≠&#96; @
💬](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Elaboration.20of.20.60.E2.89.A0.60/near/526236907).
2025-07-23 01:34:55 +00:00
Mac Malone
67bbc947af feat: lake: meta import support (#9478)
This PR adds proper Lake support for `meta import`. Module IR is now
tracked in traces and in the pre-resolved modules Lake passes to `lean
--setup`.
2025-07-23 01:17:20 +00:00
Leonardo de Moura
64219ac91e fix: assertNatCast in grind (#9476)
This PR fixes the bridge between `Nat` and `Int` in `grind cutsat`.

Closes #9467
2025-07-22 21:59:38 +00:00
Leonardo de Moura
dedd9275ec fix: mkCongrSimpCore? (#9472)
This PR fixes another issue at the `congr_simp` theorems that was
affecting Mathlib. Many thanks to Johan Commelin for creating the mwe.

closes #9466
2025-07-22 18:09:24 +00:00
Sebastian Ullrich
4dbe84dc98 chore: ensure Lake and Lean agree when .ir is needed (#9471) 2025-07-22 17:34:41 +00:00
Giles Shaw
0cc4c91800 fix: change the proof of Nat.zero_mod to rfl (#9391)
This PR replaces the proof of the simplification lemma `Nat.zero_mod`
with
`rfl` since it is, by design, a definitional equality. This solves an
issue
whereby the lemma could not be used by the simplifier when in 'dsimp'
mode.

Closes #9389

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-07-22 13:21:48 +00:00
Sebastian Graf
548d564c18 feat: Introduce mleave tactic that leaves the SPred proof mode (#9363) (#9454)
This PR introduces tactic `mleave` that leaves the `SPred` proof mode by
eta expanding through its abstractions and applying some mild
simplifications. This is useful to apply automation such as `grind`
afterwards.

Relates to #9363.
2025-07-22 11:50:16 +00:00
Sebastian Graf
2d30e3913c fix: Handle let/have in mintro (#9365) (#9451)
This PR adds support in the `mintro` tactic for introducing `let`/`have`
binders in stateful targets, akin to `intro`. This is useful when
specifications introduce such let bindings.

Closes #9365.
2025-07-22 11:35:46 +00:00
Joachim Breitner
ec13bb963f fix: PProdN.reduceProjs to also look for projection functions (#9464)
This PR makes `PProdN.reduceProjs` also look for projection functions.
Previously, all redexes were created by the functions in `PProdN`, which
used primitive projections. But with `mkAdmProj` the projection
functions creep in via the types of the `admissible_pprod_fst` theorem.
So let's just reduce both of them.

Fixes #9462.
2025-07-22 09:22:50 +00:00
Lean stage0 autoupdater
9006597f59 chore: update stage0 2025-07-22 09:47:42 +00:00
Sebastian Ullrich
e28569f2a1 perf: minimize exported codegen data (#9356)
To be documented
2025-07-22 09:05:49 +00:00
Kenny Lau
751947482f fix: use let rec for Fin.reverseInduction (#9142)
This PR changes `Fin.reverseInduction` from using well-founded recursion
to using `let rec`, which makes it have better definitional equality.
Co-authored by @digama0. See the test below:

```lean
namespace Fin

/-- The new one. -/
@[elab_as_elim] def reverseInduction' {motive : Fin (n + 1) → Sort _} (last : motive (Fin.last n))
    (cast : ∀ i : Fin n, motive i.succ → motive (castSucc i)) (i : Fin (n + 1)) : motive i :=
  let rec go (j : Nat) (h) (h2 : i ≤ j) (x : motive ⟨j, h⟩) : motive i :=
    if hi : i.1 = j then (show i = ⟨j, h⟩ by simp [← hi]) ▸ x
    else match j with
      | 0 => by omega
      | j+1 => go j (by omega) (by omega) (cast ⟨j, by omega⟩ x)
  go _ _ (by omega) last

/-- Same code but using reverseInduction'. -/
@[elab_as_elim] def lastCases' {n : Nat} {motive : Fin (n + 1) → Sort _} (last : motive (Fin.last n))
    (cast : ∀ i : Fin n, motive (castSucc i)) (i : Fin (n + 1)) : motive i :=
  reverseInduction' last (fun i _ => cast i) i

end Fin

theorem foo : (Fin.lastCases (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.lastCases (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)
theorem foo' : (Fin.lastCases' (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.lastCases' (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)

theorem bar : (Fin.reverseInduction (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.reverseInduction (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)
theorem bar' : (Fin.reverseInduction' (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.reverseInduction' (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)
```
[Link to Lean 4
Web](https://live.lean-lang.org/#project=lean-nightly&codez=HYQwtgpgzgDiDGEAEAxAlsAUJg9AWjyQBUALZYCAdyQHsKA6JPHTAAQG0IAbEAIwH0QUftzRgAukgAmEAGZIAThABuEBVAgBJYFICu8AC5o6AciQBvMDSOqkALlQYkACmBIA1EgCMASiSAkwiQAZRoFAyR+AF8XHihwhysbZGd0YHpY8OAfH0wkPJd4IXikQAAiJDR7RzdgABokRLRbNHoofXgA+utG5MK4oLby7JcKh1SXN09fPwSupvsAXlykLghwpXaAcxoXACtKgDkQAz9nEhOSACZKisATIiQdk4APSobbQAvyHbqSQEvyac6k8oLJZ5NDyEgjcr0LxIeb3JAGMhuZxQEg0agVWEfL7fJC8ACeSCgYhgSHYgATCJDg8R+QAdpEhHsCkNwNPUjvASHDKGgEYy8gAfJAABhhAD5cQSaJANiBeUgBTt3ND5mKtnDnPjaFKQCcNZKINKTr1wljxZr9SAcY8cnlVfwIi5dVq/BlsPhCEFwMh4DQZLjdOFdETgBtFCo1BptHpDMZgCZGMw2JweAIhCIuGJJDJ5BkAMJCaBmcxuByHAzRSyzZCjJyuDzePyBEJhCLRZwZF6VlypdJFJBZa35ZxGyplCFjWr/boFIr9eDtNBDZxjmsTet/V7IEaLPJKVTqLQ6fRGUzLXvOWS6NwVO3KpDDhflbAQHRVbAIiChCBgJCyGjbBwpBgPZxHmGhQC4eAACwnBeV5IIAZYTDJU2jHEgABUSBXJMJxXNWbgAMx/ChfiwlBCyKLIXCYAAxCoIBcF2QG5vm4HOFBMGXoCiFLshwCoRhWH1i4uFVEghG8ccmDvp+36/jQZgAd2zFgWYbHQS4sFcUhDjEehmF1r4wmVGM4k6XxJFMJB5EKJRNF0QxgFpMpBYQep56cRU3EQrpAkGThxlOKZSDEW+ZAybiIAKJUjn0Lu4YHlGx5IsWsIXCcG7kZpdqISF+SuRxcHZdpwXmXpgmGc4IkmURpWkVZdiwjZVG0co9GMWkcX7pGR4xuM5FpS4GUNT+nFFblg7sRpHn2l5El+L52FGXhYk1ZJ0lKN+vCRQp7WxWGXWHtGJ61sNA3OENsJZQhJWSXlakFYCRU8WZ/H6YtlUBQRq0WWRw1NXZrUOd2nURodSWqSlmHpZ2w1XTl5mMvdU2Fddz03fNb1CR9y1BcRQA)

Notice how `rfl` fails for the 1st and 5th tests that use the original
`Fin.reverseInduction`, but the 3rd and 7th tests that use the new code
in this PR succeed.

Closes #9141.

---------

Co-authored-by: Markus Himmel <markus@lean-fro.org>
2025-07-22 08:34:14 +00:00
Rob23oba
b7ab7ea745 fix: behavior of String.next (#9449)
This PR fix the behavior of `String.next` on the scalar boundary (`2 ^
63 - 1` on 64-bit platforms).

Closes #9440
2025-07-22 06:48:33 +00:00
Cameron Zwarich
6f5532f069 perf: make function types object rather than tobject (#9461) 2025-07-22 01:16:45 +00:00
Cameron Zwarich
30ca6c82e0 refactor: use named params (#9460) 2025-07-22 00:11:25 +00:00
Cameron Zwarich
968a708a9f perf: update type information in cases arms for RC optimizations (#9457)
The `isRef` check being removed here used to be an optimization, because
this structure only tracked whether ref counting operations need to be
inserted at all. Now the structure also tracks whether the value needs
to be checked for being a scalar or not, which is something that can be
refined by a `cases` arm, since inductive types can have a mix of scalar
and non-scalar constructors.
2025-07-21 23:10:11 +00:00
Cameron Zwarich
bb23700f24 chore: add named params to MonadWithReader.withReader (#9459)
This matches `MonadWithReaderOf`.
2025-07-21 23:02:19 +00:00
Cameron Zwarich
9a34f6bc95 refactor: remove questionable defaults in Context structure (#9458) 2025-07-21 22:16:14 +00:00
Cameron Zwarich
f3e1795175 refactor: clean up monad setup (#9456) 2025-07-21 21:22:20 +00:00
jrr6
d57d1fcd36 fix: prevent deriving handlers from generating ambiguous identifiers (#9371)
This PR fixes an issue that caused some `deriving` handlers to fail when
the name of the type being declared matched that of a declaration in an
open namespace.

Closes #9366
2025-07-21 17:45:54 +00:00
Lean stage0 autoupdater
e134cfea8f chore: update stage0 2025-07-21 16:24:20 +00:00
Marc Huisinga
8b8561a699 feat: improved go to definition (#9040)
This PR improves the 'Go to Definition' UX, specifically:
- Using 'Go to Definition' on a type class projection will now extract
the specific instances that were involved and provide them as locations
to jump to. For example, using 'Go to Definition' on the `toString` of
`toString 0` will yield results for `ToString.toString` and `ToString
Nat`.
- Using 'Go to Definition' on a macro that produces syntax with type
class projections will now also extract the specific instances that were
involved and provide them as locations to jump to. For example, using
'Go to Definition' on the `+` of `1 + 1` will yield results for
`HAdd.hAdd`, `HAdd α α α` and `Add Nat`.
- Using 'Go to Declaration' will now provide all the results of 'Go to
Definition' in addition to the elaborator and the parser that were
involved. For example, using 'Go to Declaration' on the `+` of `1 + 1`
will yield results for `HAdd.hAdd`, `HAdd α α α`, `Add Nat`,
``macro_rules | `($x + $y) => ...`` and `infixl:65 " + " => HAdd.hAdd`.
- Using 'Go to Type Definition' on a value with a type that contains
multiple constants will now provide 'Go to Definition' results for each
constant. For example, using 'Go to Type Definition' on `x` for `x :
Array Nat` will yield results for `Array` and `Nat`.

### Details
'Go to Definition' for type class projections was first implemented by
#1767, but there were still a couple of shortcomings with the
implementation. E.g. in order to jump to the instance in `toString 0`,
one had to add another space within the application and then use 'Go to
Definition' on that, or macros would block instances from being
displayed. Then, when the .ilean format was added, most 'Go to
Definition' requests were already handled using the .ileans in the
watchdog process, and so the file worker never received them to handle
them with the semantic information that it has available.

This PR resolves most of the issues with the previous implementation and
refactors the 'Go to Definition' control flow so that 'Go to Definition'
requests are always handled by the file worker, with the watchdog merely
using its .ilean position information to update the positions in the
response to a more up-to-date state. This is necessary because the file
worker obtains its position information from the .oleans, which need to
be rebuilt in order to be up-to-date, while the watchdog always receives
.ilean update notifications from each active file worker with the
current position information in the editor.

Finally, all of the 'Go to Definition' code is refactored to be easier
to maintain.

### Breaking changes
`InfoTree.hoverableInfoAt?` has been generalized to
`InfoTree.hoverableInfoAtM?` and now takes a general `filter` argument
instead of several boolean flags, as was the case before.
2025-07-21 15:47:44 +00:00
Lean stage0 autoupdater
51ae98ae30 chore: update stage0 2025-07-21 14:40:51 +00:00
Henrik Böving
09de5cd70e refactor: remove Lean.RBMap usages (#9260)
This PR removes uses of `Lean.RBMap` in Lean itself.

Furthermore some massaging of the import graph is done in order to avoid
having `Std.Data.TreeMap.AdditionalOperations` (which is quite
expensive) be the critical path for a large chunk of Lean. In particular
we can build `Lean.Meta.Simp` and `Lean.Meta.Grind` without it thanks to
these changes.

We did previously not conduct this change as `Std.TreeMap` was not
outperforming `Lean.RBMap` yet, however this has changed with the new
code generator.
2025-07-21 14:04:45 +00:00
Joachim Breitner
23e88b4e1d chore: test for issue #9018 (#9452) 2025-07-21 13:55:36 +00:00
Joachim Breitner
fcd60e73f8 fix: use withIncRecDepth in SizeOf deriving (#9448)
This PR addresses the lean crash (stack overflow) with nested induction
and the generation of the `SizeOf` spec lemmas, reported at #9018.

It does not address the underlying issue that in these cases, the
generated SizeOf code does not match the the SizeOf function found by
instance search, and thus the generation fails.

This seem hard to fix: `mkSizeOfMinors` would have to recognize that
given, say, `List (Id Tree)`, the derived instance (assuming there was
one for `Tree`) is not the same as for `List Tree`.

The problem seems just about as hard as getting derived SizeOf right in
the presence of nested induction and non-canonical SizeOf instances.
2025-07-21 12:43:19 +00:00
Rob23oba
b7f433c5b9 fix: behavior of String.prev (#9441)
This PR fixes the behavior of `String.prev`, aligning the runtime
implementation with the reference implementation. In particular, the
following statements hold now:
- `(s.prev p).byteIdx` is at least `p.byteIdx - 4` and at most
`p.byteIdx - 1`
- `s.prev 0 = 0`
- `s.prev` is monotone

Closes #9439
2025-07-21 10:50:14 +00:00
Sebastian Graf
f3ac38ff2c fix: Close pure, trivial goals in mvcgen (#9362) (#9447)
This PR ensures that `mvcgen` not only tries to close stateful subgoals
by assumption, but also pure Lean goals.

Closes #9362.
2025-07-21 10:12:34 +00:00
Lean stage0 autoupdater
c5a5c5572f chore: update stage0 2025-07-21 05:32:04 +00:00
Cameron Zwarich
2f7c0366f5 perf: treat partial application and eta expansion equally for specialization (#9438) 2025-07-20 14:57:21 +00:00
Cameron Zwarich
1a9757d1f6 refactor: make withReader calls more readable (#9442) 2025-07-20 13:39:35 +00:00
Mac Malone
3aaa3beeee feat: lake: job count in build success message (#9436)
This PR adds the number of jobs run to the final message Lake produces
on a successfully run of `lake build`.


**Examples**
```
Build completed successfully (1 job).
Build completed successfully (6 jobs).
```
2025-07-19 04:59:39 +00:00
Mac Malone
deef4e8e23 feat: lake: libPrefixOnWindows (#9435)
This PR adds the `libPrefixOnWindows` package and library configuration
option. When enabled, Lake will prefix static and shared libraries with
`lib` on Windows (i.e., the same way it does on Unix).
2025-07-19 04:46:42 +00:00
Mac Malone
c660f63748 refactor: lake: restore libs & exes from cache (#9434)
This PR changes the Lake local cache infrastructure to restore
executables and shared and static libraries from the cache. This means
they keep their expected names, which some use cases still rely on.
2025-07-19 03:28:42 +00:00
jrr6
b7e220039f feat: add hints for tuple projections (#9387)
This PR adds a hint to the "invalid projection" message suggesting the
correct nested projection for expressions of the form `t.n` where `t` is
a tuple and `n > 2`.

This feature was originally proposed by @nomeata in #8986.
2025-07-18 23:55:13 +00:00
jrr6
34bd6e8bfd feat: improve split error messages (#9424)
This PR improves the error messages produced by the `split` tactic,
including suggesting syntax fixes and related tactics with which it
might be confused.

Note that, to avoid clashing with the new error message styling
conventions used in these messages, this PR also updates the formatting
of the message produced by `throwTacticEx`.

Closes #6224
2025-07-18 22:36:10 +00:00
Cameron Zwarich
5cd5885da4 fix: make IRType.erased a tobject when boxing it (#9431)
This PR changes `IRType.boxed` to map `erased` to `tobject` rather than
`object`, since `erased` has a representation of a boxed scalar 0 when
we are forced to represent it at runtime. This case does not occur at
all in the Lean codebase.
2025-07-18 20:10:52 +00:00
jrr6
5f4e6a86d5 feat: update and explain "unknown constant" and "failed to infer type" errors (#9423)
This PR updates the formatting of, and adds explanations for, "unknown
identifier" errors as well as "failed to infer type" errors for binders
and definitions.

It attempts to ameliorate some of the confusion encountered in #1592 by
modifying the wording of the "header is elaborated before body is
processed" note and adding further discussion and examples of this
behavior in the corresponding error explanation.
2025-07-18 19:20:31 +00:00
Cameron Zwarich
1043569648 perf: use more precise IR types for overapplication (#9428) 2025-07-18 16:34:19 +00:00
Paul Reichert
383256defa chore: reintroduce Subarray.foldl on top of Slice.foldl (#9234)
An earlier PR (#9017) replaced certain subarray functions such as
`Subarray.foldl` with generic slice functions `Slice.foldl`. For
backward compatibility reasons, This PR reintroduces `Subarray.foldl`
etc. as aliases for the `Slice` versions.
2025-07-18 15:23:50 +00:00
Cameron Zwarich
cdab726e3d refactor: clean up creation of IR over-application (#9426) 2025-07-18 06:11:06 +00:00
Mac Malone
7b9ead4a1a chore: lake: module system tests & fixes (#9422)
This PR adds Lake tests for builds involving the Lean module system and
fixes some bugs encountered in the process. In particular, it fixes the
parsing of private imports and how Lake handles the `import all` of a
private import.
2025-07-18 02:34:13 +00:00
jrr6
6e191720b3 fix: open error explanations in new window in web editor (#9421)
This PR fixes a bug that caused error explanations to "steal" the
Infoview's container in the Lean web editor.
2025-07-17 23:20:35 +00:00
Sebastian Ullrich
9fc31abb1f chore: benchmark using USE_LAKE (#9361) 2025-07-17 18:44:29 +00:00
Markus Himmel
3878d6da85 chore: Grove: bump version (#9419) 2025-07-17 15:02:17 +00:00
Henrik Böving
097952c48f perf: simp subexpr benchmark (#9404)
This PR adds a simp benchmark to our suite, specifically targeting
caching of subexpression
rewriting results.
2025-07-17 11:53:48 +00:00
Sebastian Ullrich
e5730e9b7e refactor: module-ize remainder of Std (#9195) 2025-07-17 11:43:57 +00:00
Sebastian Ullrich
49546687d9 chore: update stage0 2025-07-17 11:54:06 +02:00
Sebastian Ullrich
2c08280854 fix: meta def should never be exposed (#9415) 2025-07-17 11:52:32 +02:00
Mac Malone
ebe68faf7f fix: lake: test script bugs w/ Mathlib & non-Linux (#9397)
This PR fixes some issues with the Lake tests on Windows and macOS. It
also avoids downloading Mathlib in the `init` test, which was currently
doing this after changes to the `math-lax` template in #8866.

To skip the Mathlib download in `init`, an undocumented `--offline`
option was added`. This option is currently meant for internal use only.
2025-07-17 07:08:00 +00:00
Leonardo de Moura
65abbd90bf perf: isArrowProposition (#9414)
This PR increases the number of cases where `isArrowProposition` returns
a result other than `.undef`. This function is used to implement the
`isProof` predicate, which is invoked on every subterm visited by
`simp`.
2025-07-17 04:12:15 +00:00
jrr6
119854e248 feat: add hints for missing structure instance fields (#9317)
This PR adds to the "fields missing" error message for structure
instance notation a code-action hint that inserts all missing fields.
2025-07-17 03:22:34 +00:00
jrr6
442ef6e64c feat: add case name hints (#9316)
This PR adds clickable code-action hints to the "invalid case name"
error message.
2025-07-17 03:22:30 +00:00
jrr6
fb462fdf9e feat: add named argument hints (#9315)
This PR adds improves the "invalid named argument" error message in
function applications and match patterns by providing clickable hints
with valid argument names. In so doing, it also fixes an issue where
this error message would erroneously flag valid match-pattern argument
names.
2025-07-17 03:22:25 +00:00
Cameron Zwarich
d667522524 refactor: remove special cases for subsingleton casesOn (#9412) 2025-07-16 23:41:41 +00:00
Cameron Zwarich
c1b5d54737 feat: compiler support for casesOn of subsingletons (#9411)
This PR adds support for compilation of `casesOn` for subsingletons. We
rely on the elaborator's type checking to restrict this to inductives in
`Prop` that can actually eliminate into `Type n`. This does not yet
cover other recursors of these types (or of inductives not in `Prop` for
that matter).
2025-07-16 23:07:32 +00:00
Sebastian Ullrich
f94d7b333a fix: do not export private instances (#9407)
Fixes #9383
2025-07-16 18:59:48 +00:00
Leonardo de Moura
d7ef2880c8 perf: avoid "dependent implications" as local E-matching theorems in grind (#9408)
This PR implements a simple optimization: dependent implications are no
longer treated as E-matching theorems in `grind`. In
`grind_bitvec2.lean`, this change saves around 3 seconds, as many
dependent implications are generated. Example:
```lean
 ∀ (h : i + 1 ≤ w), x.abs.getLsbD i = x.abs[i]
 ```
2025-07-16 17:13:52 +00:00
Sebastian Ullrich
f3944a3d49 chore: fix test 2025-07-16 17:51:42 +02:00
Sebastian Ullrich
263a77fa89 chore: update stage0 2025-07-16 16:04:47 +02:00
Sebastian Ullrich
2584b6abf9 fix: assorted module system fixes (#9406)
Encountered when porting `Std` and `Lean`
2025-07-16 13:31:08 +00:00
Markus Himmel
ca9b804163 chore: ci: specify which Linux toolchain Grove should download (#9405)
Since the old version of the workflow will run on PRs, we'll have to
"test" this on master.
2025-07-16 13:15:13 +00:00
Henrik Böving
e9ccdeecd0 perf: add a benchmark for simp on local hypotheses (#9403)
This PR adds a benchmark to our suite, specifically targeting the fact
that local hypotheses
are currently not indexed in simp and can thus cause significant
slowdowns compared to having them
as external declarations.
2025-07-16 12:16:29 +00:00
Sebastian Ullrich
2ed4f39ffe chore: adapt core to preceding syntax change 2025-07-16 13:32:11 +02:00
Sebastian Ullrich
1959e6088b chore: update stage0 2025-07-16 13:32:11 +02:00
Sebastian Ullrich
ffbb21a032 fix: order of @[expose] public section
This PR makes the order of `@[expose] public` at `section` consistent with that at `def`
2025-07-16 13:32:11 +02:00
Sebastian Ullrich
e088549330 refactor: module-ize Std.Time (#9100) 2025-07-16 09:57:53 +00:00
Mac Malone
587979341a refactor: lake: optimize module build code for new compiler (#9400)
This PR splits up `Module.recBuildLean` into smaller functions and
optimizes the implementation of `Module.cacheOutputArtifacts` for the
new compiler. Now, all functions within `Lake.Build.Module` take Lean
<1s to compile.
2025-07-16 07:27:34 +00:00
Mac Malone
180bfeaba4 feat: lake: pre-resolve module imports (#9053)
This PR updates Lake to resolve the `.olean` files for transitive
imports for Lean through the `modules` field of `lean --setup`. This
enables means the Lean can now directly use the `.olean` files from the
Lake cache without needed to locate them at a specific hierarchical
path.

Resolving transitive imports still has a performance penalty, but it is
now much less.
2025-07-16 04:21:31 +00:00
Lean stage0 autoupdater
e6cce355e3 chore: update stage0 2025-07-16 04:26:10 +00:00
Cameron Zwarich
e9b75e34b7 perf: decide whether to use _ref variants of inc/dec using IR types (#9399) 2025-07-16 03:52:58 +00:00
Leonardo de Moura
e286f20179 perf: avoid inferType at simpArith (#9398)
This PR avoids the expensive `inferType` call in `simpArith`. It also
cleans up some of the code and removes anti-patterns.
2025-07-16 03:42:26 +00:00
Lean stage0 autoupdater
d4afa3caaa chore: update stage0 2025-07-16 02:48:16 +00:00
Cameron Zwarich
e069c9eb0e perf: use IR type info to decide whether to insert RC ops (#9396)
This is mostly a refactoring that replaces other analyses with type
information, but due to the introduction of `tagged` it also has the
side effect of eliminating ref counting ops entirely for types that
always have a tagged scalar representation, e.g. `Unit`.
2025-07-16 02:02:32 +00:00
Leonardo de Moura
dc2f256448 fix: bug at mkCongrSimpCore? (#9395)
This PR fixes a bug at `mkCongrSimpCore?`. It fixes the issue reported
by @joehendrix at #9388.
The fix is just commit: afc4ba617f. The
rest of the PR is just cleaning up the file.

closes #9388
2025-07-16 00:54:31 +00:00
Cameron Zwarich
62ded77e81 chore: add a new tagged IRType for inline tagged scalars (#9394) 2025-07-16 00:42:56 +00:00
Cameron Zwarich
466e8a6c5e fix: adjust unsafe trick for upcoming optimization (#9393)
This PR fixes an unsafe trick where a sentinel for a hash table of Exprs
(keyed by pointer) is created by constructing a value whose runtime
representation can never be a valid Expr. The value chosen for this
purpose was Unit.unit, which violates the inference that Expr has no
scalar constructors. Instead, we change this to a freshly allocated Unit
× Unit value.
2025-07-16 00:10:01 +00:00
Cameron Zwarich
b131e8b97f chore: adopt tobject IRType (#9392) 2025-07-15 23:56:49 +00:00
Cameron Zwarich
d7ef2a8d1c refactor: add a CtorFieldInfo.object field for the object type (#9390) 2025-07-15 23:18:23 +00:00
jrr6
3b58a7d36b fix: improve error message when projecting from zero-field type (#9386)
This PR improves a confusing error message that occurred when attempting
to project from a zero-field structure.

Closes #9312
2025-07-15 21:32:59 +00:00
jrr6
e9a318df16 fix: reorder "application type mismatch" message (#9287)
This PR rewords the "application type mismatch" error message so that
the argument and its type precede the application expression.
2025-07-15 19:20:18 +00:00
Leonardo de Moura
166d1c0dab perf: avoid isDefEq test at simpEq simproc used in grind (#9385)
This PR replaces the `isDefEq` test in the `simpEq` simproc used in
`grind`. It is too expensive.
2025-07-15 18:38:11 +00:00
Joachim Breitner
0926d27100 chore: fix benchmark added in #9380 (#9384) 2025-07-15 18:24:34 +00:00
Henrik Böving
aa6f22d102 chore: reduce import closure of MPL (#9382)
This PR reduces the import closure of the monadic verification framework
from `Lean.Meta` to only
the submodules actually required.
2025-07-15 16:36:03 +00:00
Joachim Breitner
6adeab2160 chore: add simple simp benchmark (#9380)
A micro-benchmark for plain, mostly first-order rewriting of simp:

This uses axiom to make it independent of specific optimization (e.g.
for `Nat`).

It generates a “list” of 128 `b`s followed by 128 `a` and uses
bubble-sort to to sort it and compares it against the expected output.
2025-07-15 15:04:49 +00:00
Malhar A. Patel
6cbdd6b815 doc: correct the Option.getD docString example (#9190)
This PR corrects the second example in the `Option.getD` docString

Closes #9189
2025-07-15 12:39:58 +00:00
Henrik Böving
a8c0348300 chore: re-simp Std.LawfulEqCmp.compare_eq_iff_eq (#9377)
This PR readds `simp` annotations accidentally lost in previous PRs
2025-07-15 12:10:50 +00:00
Filippo A. E. Nuccio
08d8bed022 doc: fix a typo in Pairwise doc (#9375)
doc: fix a typo in Pairwise doc

This PR fixes a sentence in the Pairwise doc in List/Basic
2025-07-15 11:39:02 +00:00
Henrik Böving
6e9bc1359d fix: don't delay lake logging when cloning a dependency (#9332)
This PR changes the dependency cloning mechanism in lake so the log
message that lake is cloning a
dependency occurs before it is finished doing so (and instead before it
starts). This has been a
huge source of confusion for users that don't understand why lake seems
to be just stuck for no
reason when setting up a new project, the output now is:
```
λ lake +lean4 new math math
info: downloading mathlib `lean-toolchain` file
info: math: no previous manifest, creating one from scratch
info: leanprover-community/mathlib: cloning https://github.com/leanprover-community/mathlib4
<hang>
info: leanprover-community/mathlib: checking out revision 'cd11c28c6a0d514a41dd7be9a862a9c8815f8599'
```
2025-07-15 09:38:35 +00:00
Cameron Zwarich
aac501a645 refactor: split up mkExpr helper in lowerLet (#9374) 2025-07-15 05:26:21 +00:00
Cameron Zwarich
cf94e1b162 refactor: get the type of a literal from lowerLitValue (#9373)
This will let us have value-dependent types in the future for tracking
tagged/boxed values.
2025-07-15 04:46:47 +00:00
Leonardo de Moura
96e7ab078d fix: performance issue when elaborating match-expressions with many literals (#9372)
This PR fixes a performance issue that occurs when generating equation
lemmas for functions that use match-expressions containing several
literals. This issue was exposed by #9322 and arises from a combination
of factors:

1. Literal values are compiled into a chain of dependent if-then-else
expressions.
2. Dependent if-then-else expressions are significantly more expensive
to simplify than regular ones.
3. The `split` tactic selects a target, splits it, and then invokes
`simp` on the resulting subgoals. Moreover, `simp` traverses the entire
goal bottom-up and does not stop after reaching the target.

This PR addresses the issue by introducing a custom simproc that avoids
recursively simplifying nested if-then-else expressions. It does **not**
alter the user-facing behavior of the `split` tactic because such a
change would be highly disruptive. Instead, the PR adds a new flag,
`backward.split` to control the behavior of the user-facing `split`
tactic. It is currently set to `true`, i.e., the old behavior is still
the default one. In a future PR, we should set this flag to `false` by
default and begin repairing all affected proofs.

closes #9322
2025-07-15 03:52:23 +00:00
Cameron Zwarich
9d33f2ad33 chore: make IR.Arg pattern matching more exhaustive (#9370) 2025-07-14 22:46:40 +00:00
Leonardo de Moura
a4b5eecb8e perf: skip unnecessary preprocessing steps in grind when possible (#9369)
This PR optimizes the `grind` preprocessor by skipping unnecessary steps
when possible.
2025-07-14 22:05:02 +00:00
Cameron Zwarich
f224452971 chore: simplify box/unbox casting logic (#9368) 2025-07-14 21:51:09 +00:00
Sebastian Ullrich
caf815b009 feat: improve infer binder type failure message and range (#8263)
This PR improves the message and range of infer binder type failures.

---------

Co-authored-by: Joseph Rotella <7482866+jrr6@users.noreply.github.com>
2025-07-14 20:19:11 +00:00
Cameron Zwarich
c0079fd9dd perf: allow boxed scalars passed to scalar params to be borrowed (#9360) 2025-07-14 19:58:01 +00:00
Leonardo de Moura
cfb13b1689 perf: add unfoldReducible' using inShareCommon (#9367)
This PR implements a minor optimization to the `grind` preprocessor.
2025-07-14 19:04:04 +00:00
jrr6
105843519c doc: expand elab_as_elim docstring and fix typo (#9359)
This PR adds additional information from a recent Zulip thread to the
docstring for the `elab_as_elim` attribute and fixes the associated
example code.

The Zulip thread can be found
[here](https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/what.20is.20.60elab_as_elim.60/with/505631084).
2025-07-14 17:53:42 +00:00
Sebastian Ullrich
97698bfc38 chore: CI: use faster Windows runners for releases (#9357) 2025-07-14 16:26:22 +00:00
Sebastian Ullrich
7f1869016a chore: CI: do not use large runners for secondary jobs (#9352)
macOS in particular is expensive to use large machines for more than
necessary
2025-07-14 15:00:58 +00:00
Markus Himmel
0931033c72 chore: Grove: add some data (#9354) 2025-07-14 10:22:59 +00:00
Markus Himmel
a7789d863c chore: Grove: update and enable on master (#9353) 2025-07-14 09:21:51 +00:00
Leonardo de Moura
bcc6fb54c2 perf: use inShareCommon to skip preprocessing steps (#9351)
This PR optimizes the `grind` preprocessing steps by skipping steps when
the term is already present in the hash-consing table.
2025-07-14 04:53:49 +00:00
Cameron Zwarich
b04ee0de57 chore: remove outdated comments (#9349) 2025-07-14 01:15:36 +00:00
Cameron Zwarich
7a83adf10d refactor: rename mmodifyBody functions to modifyBodyM (#9348) 2025-07-14 01:01:46 +00:00
Leonardo de Moura
d642880b7d chore: remove leftovers (#9347)
after update stage0
2025-07-14 00:40:32 +00:00
Lean stage0 autoupdater
74206c755f chore: update stage0 2025-07-14 00:11:34 +00:00
Leonardo de Moura
c7b4d843e2 refactor: support for Nat in grind cutsat (#9340)
This PR modifies the encoding from `Nat` to `Int` used in `grind
cutsat`. It is simpler, more extensible, and similar to the generic
`ToInt`. After update stage0, we will be able to delete the leftovers.
2025-07-13 23:40:03 +00:00
Cameron Zwarich
c90cc392f7 fix: populate the xType field of FnBody.case (#9344)
This PR correctly populates the `xType` field of the `IR.FnBody.case`
constructor. It turns out that there is no obvious consequence for this
being incorrect, because it is conservatively recomputed by the `Boxing`
pass.
2025-07-13 21:56:07 +00:00
Leonardo de Moura
f298360ff9 refactor: more "efficient" contraint propagation theorems (#9343)
The certificates perform a single pass over the polynomials.
2025-07-13 19:52:43 +00:00
Leni Aniva
275e483885 refactor: Expose DeclNameGenerator idx (#9020)
This PR exposes the internal of DeclNameGenerator to facilitate merger
of two branches of goal state or proof snapshots.
2025-07-13 10:24:04 +00:00
Cameron Zwarich
e87ce2bd5b refactor: rename "irrelevant" to "erased" in IR (#9339)
This matches the terminology used by LCNF.
2025-07-13 04:51:34 +00:00
Cameron Zwarich
3c6a923f1b refactor: use the usize index in the CtorFieldInfo struct (#9337) 2025-07-13 03:05:13 +00:00
Cameron Zwarich
b25ef7682d chore: fix spacing (#9338) 2025-07-13 03:03:50 +00:00
Cameron Zwarich
71b5bf3ef6 fix: include ._closed decls in trace.Compiler.result output (#9336)
This PR changes the implementation of `trace.Compiler.result` to use the
decls as they are provided rather than looking them up in the LCNF mono
environment extension, which was seemingly done to save the trouble of
re-normalizing fvar IDs before printing the decl. This means that the
`._closed` decls created by the `extractClosed` pass will now be
included in the output, which was definitely confusing before if you
didn't know what was happening.
2025-07-13 02:24:00 +00:00
jrr6
8dfc71c4fd chore: remove superfluous whitespace from error message (#9335)
This PR fixes a typo that caused the "cannot infer resulting universe
level of inductive datatype" error message to have leading whitespace.
2025-07-12 23:04:02 +00:00
Leonardo de Moura
243bbd74a5 chore: compilation time for EMatch.lean (#9334)
This PR improves the compilation time for `EMatch.lean`
2025-07-12 22:01:16 +00:00
Cameron Zwarich
aba49508f1 refactor: port IR Checker to CompilerM (and thus CoreM) (#9331) 2025-07-12 15:25:46 +00:00
Leonardo de Moura
ae2a9b4688 perf: propagateEqUp (#9326)
This PR optimizes `propagateEqUp` used in `grind`.
2025-07-12 03:09:59 +00:00
Leonardo de Moura
d36fc8df67 perf: propagateBoolDiseq (#9325)
This PR optimizes the Boolean disequality propagator used in `grind`.
2025-07-12 02:20:48 +00:00
Leonardo de Moura
6c20cd08f1 perf: isDiseq and mkDiseqProof? in grind (#9324)
This PR improves the functions for checking whether two terms are
disequal in `grind`
2025-07-12 01:26:48 +00:00
Cameron Zwarich
46b04c8405 chore: lower Nat.zero in toMono (#9320)
This currently relies on the encoding pun of Nat.zero as the first
tagged constructor of Nat. Since Nat.succ is lowered to addition, it
makes sense to also lower Nat.zero to a zero literal. This might also
expose more optimization opportunities in the future.
2025-07-11 23:25:05 +00:00
Cameron Zwarich
efc101d3b4 chore: move Nat.succ lowering from toIR to toMono (#9319)
It makes more sense to do it here, since `cases` on `Nat` is also
lowered in `toMono`.
2025-07-11 22:49:41 +00:00
Cameron Zwarich
e2e36087e1 refactor: split noncomputable error into its own helper (#9314) 2025-07-11 17:30:22 +00:00
Cameron Zwarich
d4e11f754a chore: clean up loop over ctor fields (#9313) 2025-07-11 16:46:48 +00:00
Cameron Zwarich
837ea41ede fix: correctly compile irrelevant args to relevant ctor params (#9310)
This PR fixes IR constructor argument lowering to correctly handle an
irrelevant argument being passed for a relevant parameter in all cases.
This happened because constructor argument lowering (incompletely)
reimplemented general LCNF-to-IR argument lowering, and the fix is to
just adopt the generic helper functions. This is probably due to an
incomplete refactoring when the new compiler was still on a branch.
2025-07-11 15:29:12 +00:00
simon-dima
5778a3c0f2 chore: fix "isRuntimeBultinType" typo (#9307) 2025-07-11 12:27:07 +00:00
Lean stage0 autoupdater
668a892cdb chore: update stage0 2025-07-11 08:18:55 +00:00
Leonardo de Moura
0fdb63f258 perf: use mkCongrSimpForConst? (#9305)
This PR uses the `mkCongrSimpForConst?` API in `simp` to reduce the
number of times the same congruence lemma is generated. Before this PR,
`grind` would spend `1.5`s creating congruence theorems during
normalization in the `grind_bitvec2.lean` benchmark. It now spends
`0.6`s. This PR should make an even bigger difference after we merge
#9300.
2025-07-11 02:29:20 +00:00
Sebastian Graf
338456e765 feat: help simp and grind reasoning about Std.Do invariants (#9301)
This PR adds a `simp` and a `grind` annotation on `Zipper`-related
theorems to improve reasoning about `Std.Do` invariants.
2025-07-10 15:44:29 +00:00
Tasiro
18a82c04fc fix: remove BEq from (Array|Vector).(any|all)_push (#9285)
This PR removes the unnecessary requirement of `BEq α` for
`Array.any_push`, `Array.any_push'`, `Array.all_push`, `Array.all_push'`
as well as `Vector.any_push` and `Vector.all_push`.
2025-07-10 06:02:14 +00:00
Leonardo de Moura
4520206f4a chore: minor perf improvement (#9296) 2025-07-10 05:41:54 +00:00
Cameron Zwarich
9ee8e0c896 chore: remove outdated comment (#9294) 2025-07-10 03:29:22 +00:00
Leonardo de Moura
62dc8d64fa perf: use custom reduceCtorEq simproc in grind (#9293)
This PR replaces the `reduceCtorEq` simproc used in `grind` by a much
more efficient one. The default one use in `simp` is just overhead
because the `grind` normalizer is already normalizing arithmetic.
In a separate PR, we will push performance improvements to the default
`reduceCtorEq`.
2025-07-10 03:18:44 +00:00
Cameron Zwarich
7845154a3d refactor: base the IR phase of the compiler on CoreM (#9291) 2025-07-10 01:39:27 +00:00
Cameron Zwarich
66de09bc9c refactor: use getEnv/modifyEnv more in IR (#9290) 2025-07-10 00:01:56 +00:00
Cameron Zwarich
3e37eef9ea refactor: remove unused addBoxedVersion variants (#9289) 2025-07-09 23:44:18 +00:00
Cameron Zwarich
d3a4bb29a7 chore: remove comment indicating that implicit conversion should be removed (#9284) 2025-07-09 17:31:34 +00:00
Cameron Zwarich
1db5e35b59 chore: remove ABI hack for the old compiler (#9283) 2025-07-09 17:25:38 +00:00
Cameron Zwarich
efe5e9a752 refactor: remove unnecessary export attributes (#9281) 2025-07-09 16:55:00 +00:00
Cameron Zwarich
a4f38cc782 refactor: remove code marked for deletion after old compiler (#9280) 2025-07-09 15:30:11 +00:00
Cameron Zwarich
b579c5c7d8 fix: make compiler.extract_closed option work again after migration (#9279)
This PR fixes the `compiler.extract_closed` option after migrating it to
Lean (and adds a test so it would be caught in the future).
2025-07-09 14:31:58 +00:00
Cameron Zwarich
575adbae18 chore: remove now-unused Lean.Compiler.AtMostOnce (#9278) 2025-07-09 14:31:15 +00:00
Cameron Zwarich
5e19c47710 chore: remove now-unused Lean.Compiler.ConstFolding (#9277) 2025-07-09 14:18:32 +00:00
Cameron Zwarich
a7675ad4b2 chore: remove unnecessary export attributes in IR code (#9276) 2025-07-09 14:18:07 +00:00
Cameron Zwarich
d2e604f74d feat: remove the old compiler (#9275)
This PR removes the old compiler written in C++.
2025-07-09 06:00:46 +00:00
Chase Johnson
4c93ab7602 fix: typos in ISO 8601 formatted datetime (#9235) (#9263)
This PR fixes `toISO8601String` to produce a string that conforms to the
ISO 8601 format specification. The previous implementation separated the
minutes and seconds fragments with a `.` instead of a `:` and included
timezone offsets without the hour and minute fragments separated by a
`:`.

Closes #9235
2025-07-09 05:52:25 +00:00
Cameron Zwarich
625de14b23 chore: remove options from 'run' tests that are now meaningless (#9274) 2025-07-09 05:26:58 +00:00
Cameron Zwarich
b13b916b7e chore: move compiler.ir trace class registration to Lean (#9273) 2025-07-09 05:15:38 +00:00
Cameron Zwarich
9f2b796639 chore: move compiler.extract_closed option from C++ to Lean (#9272) 2025-07-09 04:36:16 +00:00
Leonardo de Moura
4955dde748 perf: grind normalizer (#9271)
This PR improves the performance of the formula normalizer used in
`grind`.
2025-07-09 03:49:44 +00:00
Cameron Zwarich
3b18ae2209 chore: move llvm.cpp from library/compiler to library (#9270) 2025-07-09 02:13:08 +00:00
Cameron Zwarich
9620cb1b90 chore: have shell.cpp use library/util.h rather than library/compiler… (#9269) 2025-07-09 01:41:04 +00:00
Cameron Zwarich
d664b6b888 fix: move lean_add_extern implementation to Lean (#9268)
This PR moves the implementation of `lean_add_extern`/`addExtern` from
C++ into Lean. I believe is the last C++ helper function from the
library/compiler directory being relied upon by the new compiler. I put
it into its own file and duplicated some code because this function
needs to execute in CoreM, whereas the other IR functions live in their
own monad stack. After the C++ compiler is removed, we can move the IR
functions into CoreM.
2025-07-09 00:02:56 +00:00
Leonardo de Moura
192c0c8e67 perf: skip canonicalization of Decidable instances and add congruence-closure support (#9267)
This PR optimizes support for `Decidable` instances in `grind`. Because
`Decidable` is a subsingleton, the canonicalizer no longer wastes time
normalizing such instances, a significant performance bottleneck in
benchmarks like `grind_bitvec2.lean`. In addition, the
congruence-closure module now handles `Decidable` instances, and can
solve examples such as:
```lean
example (p q : Prop) (h₁ : Decidable p) (h₂ : Decidable (p ∧ q)) : (p ↔ q) → h₁ ≍ h₂ := by
  grind
```
2025-07-08 21:55:40 +00:00
Cameron Zwarich
cec0c82f1c fix: support .mdata in LCNF mono types (#9266)
This PR adds support for `.mdata` in LCNF mono types (and then drops it
at the IR type level instead). This better matches the behavior of
extern decls in the C++ code of the old compiler, which is still being
used to create extern decls at the moment and will soon be replaced.

This is covered by existing tests.
2025-07-08 21:35:30 +00:00
Cameron Zwarich
4ff4ed88bc chore: move the IR interpreter from library/compiler to library (#9265) 2025-07-08 20:45:55 +00:00
Cameron Zwarich
a05311d1ec chore: split IR types out into their own header file (#9264) 2025-07-08 19:49:27 +00:00
Cameron Zwarich
f675ee2062 chore: remove unnecessary include of ir_interpreter.h (#9262) 2025-07-08 18:09:20 +00:00
Cameron Zwarich
cb127b42ac chore: rename compileDeclsNew to compileDeclsImpl (#9261) 2025-07-08 17:55:11 +00:00
Cameron Zwarich
c7c5de38b3 chore: clean up getDeclNamesForCodeGen (#9259) 2025-07-08 17:00:46 +00:00
Cameron Zwarich
6ad12525ad chore: make compileDecls and friends take an Array rather than a List (#9257) 2025-07-08 16:18:44 +00:00
Cameron Zwarich
bb5df157bc chore: remove unused optional parameter from compileDecls (#9255) 2025-07-08 15:31:06 +00:00
Sebastian Graf
77442f5486 chore: revert DefEq changes until it has passed proper review (#9254) 2025-07-08 14:54:18 +00:00
Hagb (Junyu Guo 郭俊余)
97aca690d0 fix: walk through types of axioms in collectAxioms (#8842)
This PR fixes the bug that `collectAxioms` didn't collect axioms
referenced by other axioms. One of the results of this bug is that
axioms collected from a theorem proved by `native_decide` may not
include `Lean.trustCompiler`.

Closes #8840.
2025-07-08 14:42:11 +00:00
Cameron Zwarich
173629ebd5 chore: remove compiler.enableNew option (#9252) 2025-07-08 14:17:05 +00:00
Cameron Zwarich
beeeead99f chore: remove mentions of the compiler being new from trace messages (#9253) 2025-07-08 14:15:15 +00:00
Lean stage0 autoupdater
d38c36001d chore: update stage0 2025-07-08 14:35:54 +00:00
Sebastian Graf
7386cc3b12 chore: Turn Std.Do.Triple elaborator into a macro (#9251)
This PR demotes the builtin elaborators for `Std.Do.PostCond.total` and
`Std.Do.Triple` into macros, following the DefEq improvements of #9015.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-08 13:57:22 +00:00
Henrik Böving
7958e01b1c perf: basic micro benchmarks for Std.Data.TreeMap (#9250)
This PR adds micro-benchmarks for `Std.Data.TreeMap` in the same style
as for the hashmap.
2025-07-08 13:55:13 +00:00
Lean stage0 autoupdater
47e8483b38 chore: update stage0 2025-07-08 13:35:02 +00:00
Sebastian Graf
0b2bdaebd6 fix: More stuck definitional equalities involving smart unfoldings (#8766) (#9015)
This PR makes `isDefEq` detect more stuck definitional equalities
involving smart unfoldings. Specifically, if `t =?= defn ?m` and `defn`
matches on its argument, then this equality is stuck on `?m`. Prior to
this change, we would not see this dependency and simply return `false`.

Fixes #8766.

Co-authored-by: Kyle Miller <kmill31415@gmail.com>
2025-07-08 12:56:50 +00:00
Kyle Miller
ac600853c0 fix: let the congr tactic handle "under-applied" applications (#9225)
This PR improves the `congr` tactic so that it can handle function
applications with fewer arguments than the arity of the head function.
This also fixes a bug where `congr` could not make progress with
`Set`-valued functions in Mathlib, since `Set` was being unfolded and
making such functions have an apparently higher arity.

This addresses issue #2128 for the `congr` tactic, but not `simp` and
others.
2025-07-08 11:48:08 +00:00
Luisa Cicolini
77a0c2bf9b feat: add BitVec.clzAuxRec_eq_clzAuxRec_of_getLsbD_false (#9249)
This PR adds theorem `BitVec.clzAuxRec_eq_clzAuxRec_of_getLsbD_false` as
a more general statement than `BitVec.clzAuxRec_eq_clzAuxRec_of_le`,
replacing the latter in the bitblaster too.
2025-07-08 10:40:40 +00:00
Henrik Böving
46c43c3ecb perf: first set of HashMap benchmarks (#9233)
This PR adds basic microbenchmarks for `Std.Data.HashMap`
2025-07-08 08:11:52 +00:00
Cameron Zwarich
6de68dd8ef chore: remove compiler.enableNew=true from a test and rename it (#9247) 2025-07-08 05:49:57 +00:00
Cameron Zwarich
97fd75c660 chore: remove redundancy in toMono trivial structure check (#9245) 2025-07-08 05:07:16 +00:00
Leonardo de Moura
cf6a182f69 chore: profile grind satellite solvers (#9246) 2025-07-08 05:05:39 +00:00
Leonardo de Moura
655c7ab548 perf: optimize instance generation in grind linarith (#9244)
This PR improves the instance generation in the `grind linarith` module.
2025-07-08 05:04:06 +00:00
Cameron Zwarich
70368ed1a5 chore: reduce rightward drift (#9243) 2025-07-08 03:41:37 +00:00
Cameron Zwarich
765f98770b chore: improve pattern matching (#9242) 2025-07-08 03:36:34 +00:00
Leonardo de Moura
05630fc149 perf: synthesize ToInt instances on demand (#9241)
This PR ensures that the type class instances used to implement the
`ToInt` adapter (in `grind cutsat`) are generated on demand.
2025-07-08 02:36:16 +00:00
Cameron Zwarich
2d173615ba chore: remove unreachable branches (#9240)
There is a global `tryIrDecl?` check above all of this code.
2025-07-08 00:16:12 +00:00
Cameron Zwarich
b2920d6410 chore: consolidate noncomputable diagnostics (#9239) 2025-07-07 23:39:49 +00:00
Leonardo de Moura
aee2da809a chore: test for issue #9216 (#9238)
This PR adds a new test with the analysis for issue #9216.
2025-07-07 23:25:25 +00:00
Leonardo de Moura
2bf9130b63 chore: tests for #9206 (#9237)
Add examples in issue #9206 and Zulip thread as tests for `grind`.
2025-07-07 23:01:38 +00:00
Sebastian Graf
67d9d9d936 chore: Update CODEOWNERS (#9232)
Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-07 13:11:41 +00:00
Sebastian Graf
0c5946ab3f feat: Make Std.Do universe polymorphic (#9194)
This PR makes the logic and tactics of `Std.Do` universe polymorphic, at
the cost of a few definitional properties arising from the switch from
`Prop` to `ULift Prop` in the base case `SPred []`.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-07 13:11:41 +00:00
Paul Reichert
98e4b2882f refactor: migrate to new ranges (#8841)
This PR migrates usages of `Std.Range` to the new polymorphic ranges.

This PR unfortunately increases the transitive imports for
frequently-used parts of `Init` because the ranges now rely on iterators
in order to provide their functionality for types other than `Nat`.
However, iteration over ranges in compiled code is as efficient as
before in the examples I checked. This is because of a special
`IteratorLoop` implementation provided in the PR for this purpose.

There were two issues that were uncovered during migration:

* In `IndPredBelow.lean`, migrating the last remaining range causes
`compilerTest1.lean` to break. I have minimized the issue and came to
the conclusion it's a compiler bug. Therefore, I have not replaced said
old range usage yet (see #9186).
* In `BRecOn.lean`, we are publicly importing the ranges. Making this
import private should theoretically work, but there seems to be a
problem with the module system, causing the build to panic later in
`Init.Data.Grind.Poly` (see #9185).
* In `FuzzyMatching.lean`, inlining fails with the new ranges, which
would have led to significant slowdown. Therefore, I have not migrated
this file either.
2025-07-07 12:41:53 +00:00
Henrik Böving
6e98dfbc64 perf: bv_decide rewriting benchmark (#9231)
This PR adds a benchmark for the rewriting engine of bv_decide, based on
a problem extracted from
SMT-LIB. Note that this problem has significant elaboration time itself
due to its sheer size though
the overall execution time is split approximately 50:50 between
elaboration and rewriting.
2025-07-07 10:24:08 +00:00
Cameron Zwarich
e7e4119cf4 chore: move handling of Quot.{mk, lcInv} from toIR to toMono (#9230) 2025-07-07 05:11:23 +00:00
Cameron Zwarich
6cf8828ce7 chore: remove unused code in the axiom path of toIR (#9229)
This must have been the result of an earlier refactoring, since there
are no axioms with IR decls.
2025-07-07 03:45:39 +00:00
Leonardo de Moura
5d46391dde perf: generate grind ring instances on demand (#9228)
This PR improves the startup time for `grind ring` by generating the
required type classes on demand. This optimization is particularly
relevant for files that make hundreds of calls to `grind`, such as
`tests/lean/run/grind_bitvec2.lean`. For example, before this change,
`grind` spent 6.87 seconds synthesizing type classes, compared to 3.92
seconds after this PR.
2025-07-07 03:29:42 +00:00
Cameron Zwarich
c9debdaf2a chore: move lcUnreachable handling from toIR to toLCNF (#9227)
We can probably remove `lcUnreachable` once we delete the old compiler,
but for now it makes more sense to move it earlier, since LCNF already
has `Code.unreachable`.
2025-07-07 02:17:30 +00:00
Cameron Zwarich
9b7a14b156 fix: erase args for erased app params in toMono (#9224)
This PR changes the `toMono` pass to consider the type of an application
and erase all arguments corresponding to erased params. This enables a
lightweight form of relevance analysis by changing the mono type of a
decl. I would have liked to unify this with the behavior for
constructors, but my attempt to give constructors the same behavior in
#9222 (which was in preparation for this PR) had a minor performance
regression that is really incidental to the change. Still, I decided to
hold off on it for the time being. In the future, we can hopefully
extend this to constructors, extern decls, etc.
2025-07-06 23:27:48 +00:00
Cameron Zwarich
ff5d96096a chore: use Array instead of PArray in elimDeadBranches state (#9220)
This is alway used linearly.
2025-07-06 21:31:47 +00:00
Cameron Zwarich
53d4139cf1 chore: revert #9218 (#9223)
I thought I understood why the the minor !bench performance regression
was spurious, but now I'm not so sure.
2025-07-06 15:33:10 +00:00
Cameron Zwarich
c1f1287e24 fix: delete code with false assumption that LCNF local vars can occur in types (#9221)
This PR removes code that has the false assumption that LCNF local vars
can occur in types. There are other comments in `ElimDead.lean`
asserting that this is not possible, so this must have been a change
early in the development of the new compiler.
2025-07-06 15:04:13 +00:00
Cameron Zwarich
4322a0c7d3 fix: make LCNF elimDeadBranches more optimistic on unsafe decls (#9218)
This PR makes the LCNF `elimDeadBranches` pass handle unsafe decls a bit
more carefully. Now the result of an unsafe decl will only become ⊤ if
there is value flow from a recursive call.
2025-07-06 13:28:07 +00:00
Cameron Zwarich
d0e097cd1d chore: remove IRType.{isStruct,isUnion} (#9219)
These are used by the checker for `.ctor`, but I don't think that that
unboxed types will reuse `.ctor`, whose implementation details are
intimately connected to our runtime representation of objects.
2025-07-06 13:24:24 +00:00
Cameron Zwarich
bd7e6c3c61 chore: use ``-prefixed Names when possible (#9217) 2025-07-06 12:58:13 +00:00
Leonardo de Moura
1443982924 perf: restore cache at withoutModifyingMCtx (#9215)
instead of resetting it.
2025-07-06 04:18:37 +00:00
Leonardo de Moura
15586e28a8 feat: local and scoped grind_pattern (#9214)
This PR implements support for local and scoped `grind_pattern`
commands.
2025-07-05 20:36:56 -07:00
Cameron Zwarich
6f5fdf5c3e chore: adopt do notation in IR checker (#9213)
I plan to make some changes here in the future, so I figured it would be
good to make it a bit more idiomatic first.
2025-07-06 02:39:03 +00:00
Eric Wieser
bd06e07624 fix: make the name in dependsOnNoncomputable clickable (#9207)
This PR makes the offending declaration clickable in the error message
produced when something should be marked `noncomputable`.
2025-07-05 21:28:35 +00:00
Leonardo de Moura
2cf6c2ddc9 feat: track type class inference time in grind (#9211) 2025-07-05 20:24:32 +00:00
Cameron Zwarich
38d4dc7058 chore: add deriving Repr to IR.Arg (#9210)
This is helpful when debugging.
2025-07-05 19:57:41 +00:00
Cameron Zwarich
149fc2173c fix: correctly handle constructor params in elimDeadBranches (#9209)
This PR changes the `getLiteral` helper function of `elimDeadBranches`
to correctly handle inductives with constructors. This function is not
used as often as it could be, which makes this issue rare to hit outside
of targeted test cases.
2025-07-05 19:52:12 +00:00
Leonardo de Moura
12536d2015 chore: remove old grind normalizers (#9205) 2025-07-05 06:19:34 +00:00
Cameron Zwarich
36c036d952 chore: replace custom instances with deriving for IR types (#9204) 2025-07-05 05:43:07 +00:00
Lean stage0 autoupdater
bebffc0d20 chore: update stage0 2025-07-05 05:51:10 +00:00
Leonardo de Moura
dd7bc0e643 perf: simproc for grind normalizations and decls to unfold (#9202)
This PR extends the `Eq` simproc used in `grind`. It covers more cases
now. It also adds 3 reducible declarations to the list of declarations
to unfold.
2025-07-05 05:13:49 +00:00
Cameron Zwarich
264aac4a33 chore: convert local functions to use where instead (#9203) 2025-07-05 05:10:55 +00:00
Leonardo de Moura
d981a2a9a8 chore: remove old normalizers (#9201) 2025-07-05 02:43:00 +00:00
Lean stage0 autoupdater
2ca6c3bf4d chore: update stage0 2025-07-05 02:09:15 +00:00
Leonardo de Moura
722ab706c8 perf: normalize exists expressions using a simproc in grind (#9200)
This PR implements `exists` normalization using a simproc instead of
rewriting rules in grind. This is the first part of the PR, after update
stage0, we must remove the normalization theorems.
2025-07-05 01:37:36 +00:00
Lean stage0 autoupdater
9697c7264d chore: update stage0 2025-07-05 01:13:38 +00:00
Leonardo de Moura
01b0c3e0cc perf: unfold GT.gt and GE.ge in the grind normalizer (#9199) 2025-07-05 00:41:43 +00:00
Cameron Zwarich
37cffbda51 fix: consider Prop-rebundled higher-order params to be fixed (#9198)
This PR changes the compiler's specialization analysis to consider
higher-order params that are rebundled in a way that only changes their
`Prop` arguments to be fixed. This means that they get specialized with
a mere `@[specialize]`, rather than the compiler having to opt-in to
more aggressive parameter-specific specialization.
2025-07-05 00:02:24 +00:00
Leonardo de Moura
f5e47480f2 chore: #9196 part 2 (#9197)
#9196 part 2 after update stage0
2025-07-04 23:27:00 +00:00
Lean stage0 autoupdater
66ffd8d5c2 chore: update stage0 2025-07-04 21:12:35 +00:00
Leonardo de Moura
162e81af57 perf: normalize forall expressions using a simproc in grind (#9196)
This PR implements `forall` normalization using a simproc instead of
rewriting rules in `grind`. This is the first part of the PR, after
update stage0, we must remove the normalization theorems.
2025-07-04 20:41:02 +00:00
Leonardo de Moura
2bf4192ab7 fix: unexpected kernel projection issue in grind (#9193)
This PR fixes the unexpected kernel projection issue reported by issue
#9187

closes #9187
2025-07-04 17:17:40 +00:00
Lean stage0 autoupdater
106d50e46c chore: update stage0 2025-07-04 13:05:44 +00:00
Sebastian Graf
d89f336db2 fix: Scope PostCond.total to Std.Do by making it non-builtin (#9184)
This PR fixes stealing of `⇓` syntax by the new notation for total
postconditions by demoting it to non-builtin syntax and scoping it to
`Std.Do`.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-04 12:33:45 +00:00
Leonardo de Moura
e9a55bfff7 chore: move test to run (#9183) 2025-07-04 00:33:39 +00:00
Leonardo de Moura
55d5ace68e feat: pattern inference using symbol priorities in grind (#9182)
This PR tries to improve the E-matching pattern inference for `grind`.
That said, we still need better tools for annotating and maintaining
`grind` annotations in libraries.

closes #9125
2025-07-03 16:47:38 -07:00
Sebastian Ullrich
357b5f9ed8 chore: CI: restore cache in update-stage0 (#9179)
Avoid rebuilding stage 0 all the time
2025-07-03 20:55:14 +00:00
Cameron Zwarich
b1e5ecc582 chore: add a #guard_msgs to tests/lean/run/instanceUsingFalse.lean (#9180)
This test originally failed by hitting unreachable code, which is caught
by the test harness, but it's probably good to also check the result.
2025-07-03 20:42:12 +00:00
Paul Reichert
cd445dce76 refactor: replace some Subarray functions with generic slice functions (#9017)
This PR removes the `Subarray`-specific `toArray`, `foldlM` and `foldl`
methods and instead provides these operations on `Std.Slice`, which are
implemented with the `ToIterator` instance of the slice. Calling
`subarray.toArray` etc. still works, since `Subarray` is an abbreviation
for `Slice _`.

Because the benchmarks are not so clear, to be safe, I will merge this
only after the release. In contrast to the ranges, the iteration over
slices is not quite as efficient as the old `Subarray`-specific
implementation, which would require either more optimizations in the
iterator library (special `IteratorLoop` and `IteratorCollect`
implementations) or better unboxing support by the compiler.
2025-07-03 19:33:19 +00:00
Cameron Zwarich
501993eb7f fix: don't pull instances depending on erased propositions (#9177)
This PR makes the `pullInstances` pass avoid pulling any instance
expressions containing erased propositions, because we don't correctly
represent the dependencies that remain after erasure.
2025-07-03 19:17:25 +00:00
Mac Malone
9ed51959ef refactor: ignore the setup-file header in the server for now (#9163)
This PR disables the use of the header produced by `lake setup-file` in
the server for now. It will be re-enabled once Lake takes into account
the header given by the server when processing workspace modules.
Without that, `setup-file` header can produce odd behavior when the file
on disk and in an editor disagree on whether the file participates in
the module system.
2025-07-03 17:58:07 +00:00
Eric Wieser
0106ca3bec fix: undefined symbol without LEAN_USE_GMP (#9106)
This PR fixes `undefined symbol: lean::mpz::divexact(lean::mpz const&,
lean::mpz const&)` when building without `LEAN_USE_GMP`

This fixes a regression in #8089
2025-07-03 16:50:21 +00:00
Sebastian Ullrich
ba7135d73c fix: exposed wellfounded recursion (#9173)
This PR fixes an incompatibility in the experimental module system when
trying to combine wellfounded recursion with public exposed definitions.
2025-07-03 16:48:15 +00:00
Joachim Breitner
47b795a302 chore: CI: run stage0 update on faster runner (#9178)
To avoid it losing races against the merge queue.
2025-07-03 16:14:46 +00:00
Lean stage0 autoupdater
0b6df7d6a4 chore: update stage0 2025-07-03 16:14:28 +00:00
Sebastian Graf
c6689584ea fix: split ifs in mvcgen rather than relying on a spec (#9176)
This PR makes `mvcgen` split ifs rather than applying specifications.
Doing so fixes a bug reported by Rish.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-03 14:29:17 +00:00
grunweg
a7c982204e doc: use modern configuration syntax in the Simp.Config documentation (#9174)
The new config syntax is preferred for new code: change the
documentation to use it.

This was [discussed on
zulip](https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/Using.20config.20vs.20optConfig.20in.20language.20documentation/with/526948836).
2025-07-03 14:16:37 +00:00
François G. Dorais
77d79f705f fix: typos in Std.Classes.Ord.Basic (#9145)
This PR fixes two typos.
2025-07-03 12:04:25 +00:00
Leonardo de Moura
ff130a25a2 fix: bug at matchEqBwdPat (#9172)
This PR fixes a bug at `matchEqBwdPat`. The type may contain pattern
variables.
2025-07-03 07:05:01 +00:00
Kim Morrison
c06af84d9f fix: refactor grind's module/ring design to avoid a diamond (#9168)
This PR resolves a defeq diamond, which caused a problem in Mathlib:
```
import Mathlib

example (R : Type) [I : Ring R] :
  @AddCommGroup.toGrindIntModule R (@Ring.toAddCommGroup R I) =
    @Lean.Grind.Ring.instIntModule R (@Ring.toGrindRing R I) := rfl -- fails
```
2025-07-03 06:50:46 +00:00
Leonardo de Moura
5f818826d1 feat: add [grind symbol <prio>] attribute (#9169)
This PR adds the attribute `[grind symbol <prio>]`. This is just the
first part of the PR.
2025-07-03 06:06:55 +00:00
Cameron Zwarich
c8ab8f45aa chore: share duplicated code for enum scalar representation (#9170) 2025-07-03 05:33:35 +00:00
Mac Malone
6f85e32501 fix: lake: recreate static archives & use T, not --thin (#9165)
This PR fixes two issues with Lake's process of creating static
archives.

Lake now always recreates static archives by first deleting any existing
one and then recreating it. `ar rcs` does not remove delete files, so
running it when the archive already exists can leave behind "ghost"
symbols of removed object files.

Second, Lake now use `T` rather than `--thin` to create thin archives.
While `--thin` is the recommended spelling, older versions of LLVM `ar`
do not support it. Thus, either choice produces tradeoffs. `T` is chosen
to make Lake consistent with the Lean core's own (Make) build scripts.
2025-07-03 03:33:10 +00:00
Cameron Zwarich
174b1301d8 chore: remove VarInfo defaults in IR RC pass (#9167)
These defaults don't make the code easier to understand.
2025-07-03 03:15:07 +00:00
Cameron Zwarich
01d32aa408 chore: add test for #9156 after stage0 update (#9166)
Fixes #9156.
2025-07-03 02:06:21 +00:00
Lean stage0 autoupdater
c832577470 chore: update stage0 2025-07-03 01:40:52 +00:00
Cameron Zwarich
cc7c9b48a0 fix: don't inline computed fields _override implementations in base phase (#9159)
This PR enforces the non-inlining of _override impls in the base phase
of LCNF compilation. The current situation allows for constructor/cases
mismatches to be exposed to the simplifier, which triggers an assertion
failure. The reason this didn't show up sooner for Expr is that Expr has
a custom extern implementation of its computed field getter.

Fixes #9156.
2025-07-03 00:26:01 +00:00
Cameron Zwarich
2b788b1a62 chore: make tests/lean/run/2291.lean less sensitive (#9164)
This test was originally checked in for a panic in the pretty printer,
but at some point the output of every LCNF simp pass was added to
#guard_msgs output. Since this is printing LCNF built by the stage0
compiler, this causes a lot of unnecessary churn.
2025-07-02 23:27:06 +00:00
Mac Malone
2e8102424f refactor: lake: use r for ir key in content hashes (#9162)
This PR changes the key Lake uses for the `,ir` artifact in the content
hash data structure to `r`, maintaining the convention of single
character key names.
2025-07-02 22:59:13 +00:00
Rob23oba
a0bb5f4961 chore: fixes for #9158 after stage0 update (#9161) 2025-07-02 18:46:21 +00:00
Lean stage0 autoupdater
921d252253 chore: update stage0 2025-07-02 18:26:42 +00:00
Rob23oba
3ede96accc fix: use patternIgnore(...) in grind syntax (#9158)
This PR fixes the syntax of `grind` modifiers to use `patternIgnore` for
cases where both unicode and ascii variants are matched. This fixes an
issue where several variants of grind syntax weren't accepted (e.g.
`@[grind ← gen]`). Additionally, this reduces the chance that we get
another syntax matching bootstrap hell.
2025-07-02 17:14:21 +00:00
Rob23oba
7aca460c11 fix: add groups around simpLemma and grindLemma syntax (#9157)
This PR wraps `simpLemma` and `grindLemma` in `ppGroup` to make sure
that the modifiers aren't printed separately from the term / identifier.
Example:
```
simp only [very_long_lemma_oh_no_can_you_please_stop_we're_getting_to_the_limit, ←
  wait_this_is_rewritten_backwards_oh_uhh_where's_the_arrow_you_ask?_oh_wait_it's_up_there!]
==>
simp only [very_long_lemma_oh_no_can_you_please_stop_we're_getting_to_the_limit,
  ← wait_this_is_rewritten_backwards_and_wow_it's_very_clear_and_obvious]
```
2025-07-02 15:11:51 +00:00
Cameron Zwarich
8954354216 fix: tighten IR typing rules for applications of closures (#9154)
This PR tightens the IR typing rules around applications of closures.
When re-reading some code, I realized that the code in `mkPartialApp`
has a clear typo—`.object` and `type` should be swapped. However, it
doesn't matter, because later IR passes smooth out the mismatch here. It
makes more sense to be strict up-front and require applications of
closures to always return an `.object`.
2025-07-02 14:06:24 +00:00
Joachim Breitner
977ae92e43 fix: module system: remove WellFounded-specific hacks (#9143)
This PR removes a rather ugly hack in the module system, exposing the
bodies of theorems whose type mention `WellFounded`.

The original motivation was that reducing well-founded definitions (e.g.
in `by rfl`) requires reducing proofs, so they need to be available.

But reducing proofs is generally fraught with peril, and we have been
nudging our users away from using it for a while, e.g. in #5182. Since
the module system is opt-in and users will gradually migrate to it, it
may be reasonable to expect them to avoid reducing well-founded
recursion in the process

This way we don't need hacks like this (which, without evidence, I
believe would be incomplete anyways) and we get the nice guarantee that
within the module system, theorems bodies are always private.
2025-07-02 11:58:50 +00:00
Sebastian Ullrich
2f162005b8 refactor: module-ize Std.Data.DHashMap (#9098) 2025-07-02 10:00:17 +00:00
Paul Reichert
84cd2c49eb feat: remove unnecessary decidability requirements (#9096)
This PR removes some unnecessary `Decidable*` instance arguments by
using lemmas in the `Classical` namespace instead of the `Decidable`
namespace.

This might lead to some additional dependency on classical axioms, but
large parts of the standard library are relying on them either way.
2025-07-02 06:20:50 +00:00
Paul Reichert
561f347f5a feat: universe-polymorphic loop operations on pure iterators (#9135)
This PR allows the result type of `forIn`, `foldM` and `fold` on pure
iterators (`Iter`) to be in a different universe than the iterators.
2025-07-02 06:18:20 +00:00
Leonardo de Moura
a4a3a3b596 feat: improve linarith markVars (#9153)
This PR improves the linarith `markVars`, and ensures it does not
produce spurious issue messages.
2025-07-02 05:05:10 +00:00
David Thrane Christiansen
8c0cff83bd doc: update obsolete docstring for registerDerivingHandler (#9152)
This PR fixes an obsolete docstring for `registerDerivingHandler`
2025-07-02 04:03:00 +00:00
Leonardo de Moura
094dd588d6 chore: simproc and helper theorems for grind (#9151) 2025-07-02 03:57:12 +00:00
Rob23oba
e6954b7837 fix: revert state on compilation failure (new compiler) (#8691)
This PR ensures that the state is reverted when compilation using the
new compiler fails. This is especially important for noncomputable
sections where the compiler might generate half-compiled functions which
may then be erroneously used while compiling other functions.
2025-07-02 03:42:00 +00:00
Leonardo de Moura
4a539715c8 fix: missing case at CommRing.toPoly (#9150)
This PR adds a missing case in the `toPoly` function used in `grind`.
2025-07-02 02:53:48 +00:00
Leonardo de Moura
2b1b2ed45c feat: pow_add for any semirings in grind (#9149)
This PR generalizes the `a^(m+n)` grind normalizer to any semirings.
Example:
```
variable [Field R]

example (M : R) (h₀ : M ≠ 0) {n : Nat} (hn : n > 0) : M ^ n / M = M ^ (n - 1) := by
  cases n <;> grind
```
2025-07-02 01:43:35 +00:00
Leonardo de Moura
b67fb4fa66 feat: polynomial operations with deep recursion and heartbeat checks (#9146)
This PR adds "safe" polynomial operations to `grind ring`. The use the
usual combinators: `withIncRecDepth` and `checkSystem`.
2025-07-02 00:05:28 +00:00
Cameron Zwarich
2864efb222 feat: support enums modulo irrelevance (#9144)
This PR adds support for representing more inductive as enums,
summarized up as extending support to those that fail to be enums
because of parameters or irrelevant fields. While this is nice to have,
it is actually motivated by correctness of a future desired
optimization. The existing type representation is unsound if we
implement `object`/`tobject` distinction between values guaranteed to be
an object pointer and those that may also be a tagged scalar. In
particular, types like the ones added in this PR's tests would have all
of their constructors encoded via tagged values, but under the natural
extension of the existing rules of type representation they would be
considered `object` rather than `tobject`.
2025-07-01 22:35:50 +00:00
Cameron Zwarich
f91d6ce16f chore: cache IR types of named types (#9140)
This PR converts the `lowerEnumToScalarType?` cache to a cache of IR
types of named types. This is more sensible than just focusing on the
enum optimization, and due to uniform representation of polymorphism we
have to compile `Constant T1` and `Constant T2` to the same
representation.
2025-07-01 21:39:05 +00:00
dependabot[bot]
8e5dfb0fd1 chore: CI: bump softprops/action-gh-release from 2.2.2 to 2.3.2 (#9139)
Bumps
[softprops/action-gh-release](https://github.com/softprops/action-gh-release)
from 2.2.2 to 2.3.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/releases">softprops/action-gh-release's
releases</a>.</em></p>
<blockquote>
<h2>v2.3.2</h2>
<ul>
<li>fix: revert fs <code>readableWebStream</code> change</li>
</ul>
<h2>v2.3.1</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: fix file closing issue by <a
href="https://github.com/WailGree"><code>@​WailGree</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/629">softprops/action-gh-release#629</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/WailGree"><code>@​WailGree</code></a>
made their first contribution in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/629">softprops/action-gh-release#629</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/softprops/action-gh-release/compare/v2.3.0...v2.3.1">https://github.com/softprops/action-gh-release/compare/v2.3.0...v2.3.1</a></p>
<h2>v2.3.0</h2>
<!-- raw HTML omitted -->
<ul>
<li>Migrate from jest to vitest</li>
<li>Replace <code>mime</code> with <code>mime-types</code></li>
<li>Bump to use node 24</li>
<li>Dependency updates</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/softprops/action-gh-release/compare/v2.2.2...v2.3.0">https://github.com/softprops/action-gh-release/compare/v2.2.2...v2.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md">softprops/action-gh-release's
changelog</a>.</em></p>
<blockquote>
<h2>2.3.2</h2>
<ul>
<li>fix: revert fs <code>readableWebStream</code> change</li>
</ul>
<h2>2.3.1</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: fix file closing issue by <a
href="https://github.com/WailGree"><code>@​WailGree</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/629">softprops/action-gh-release#629</a></li>
</ul>
<h2>2.3.0</h2>
<ul>
<li>Migrate from jest to vitest</li>
<li>Replace <code>mime</code> with <code>mime-types</code></li>
<li>Bump to use node 24</li>
<li>Dependency updates</li>
</ul>
<h2>2.2.2</h2>
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: updating release draft status from true to false by <a
href="https://github.com/galargh"><code>@​galargh</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/316">softprops/action-gh-release#316</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore: simplify ref_type test by <a
href="https://github.com/steinybot"><code>@​steinybot</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/598">softprops/action-gh-release#598</a></li>
<li>fix(docs): clarify the default for tag_name by <a
href="https://github.com/muzimuzhi"><code>@​muzimuzhi</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/599">softprops/action-gh-release#599</a></li>
<li>test(release): add unit tests when searching for a release by <a
href="https://github.com/rwaskiewicz"><code>@​rwaskiewicz</code></a> in
<a
href="https://redirect.github.com/softprops/action-gh-release/pull/603">softprops/action-gh-release#603</a></li>
<li>dependency updates</li>
</ul>
<h2>2.2.1</h2>
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: big file uploads by <a
href="https://github.com/xen0n"><code>@​xen0n</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/562">softprops/action-gh-release#562</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore(deps): bump <code>@​types/node</code> from 22.10.1 to 22.10.2
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/559">softprops/action-gh-release#559</a></li>
<li>chore(deps): bump <code>@​types/node</code> from 22.10.2 to 22.10.5
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/569">softprops/action-gh-release#569</a></li>
<li>chore: update error and warning messages for not matching files in
files field by <a
href="https://github.com/ytimocin"><code>@​ytimocin</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/568">softprops/action-gh-release#568</a></li>
</ul>
<h2>2.2.0</h2>
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="72f2c25fcb"><code>72f2c25</code></a>
release 2.3.2</li>
<li><a
href="552dc5524b"><code>552dc55</code></a>
fix: revert <code>fs:readableWebStream</code> change (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/632">#632</a>)</li>
<li><a
href="f3cad8bcbf"><code>f3cad8b</code></a>
release 2.3.1</li>
<li><a
href="07a2257003"><code>07a2257</code></a>
fix: fix file closing issue (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/629">#629</a>)</li>
<li><a
href="d5382d3e6f"><code>d5382d3</code></a>
release 2.3.0</li>
<li><a
href="a0e2122208"><code>a0e2122</code></a>
feat: migrate from jest to vitest (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/626">#626</a>)</li>
<li><a
href="8836085300"><code>8836085</code></a>
chore: replace <code>mime</code> with <code>mime-types</code> (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/624">#624</a>)</li>
<li><a
href="86463358d8"><code>8646335</code></a>
chore: bump node to 20.19.2</li>
<li><a
href="46b284799f"><code>46b2847</code></a>
chore(deps): bump the npm group across 1 directory with 5 updates (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/623">#623</a>)</li>
<li><a
href="37fd9d0351"><code>37fd9d0</code></a>
chore(deps): bump undici from 5.28.5 to 5.29.0 (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/621">#621</a>)</li>
<li>Additional commits viewable in <a
href="da05d55257...72f2c25fcb">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=softprops/action-gh-release&package-manager=github_actions&previous-version=2.2.2&new-version=2.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 21:22:15 +00:00
dependabot[bot]
5c86fd271f chore: CI: bump dawidd6/action-download-artifact from 10 to 11 (#9137)
Bumps
[dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
from 10 to 11.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dawidd6/action-download-artifact/releases">dawidd6/action-download-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v11</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/dawidd6/action-download-artifact/compare/v10...v11">https://github.com/dawidd6/action-download-artifact/compare/v10...v11</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ac66b43f0e"><code>ac66b43</code></a>
node_modules: upgrade</li>
<li><a
href="9b54a0a70c"><code>9b54a0a</code></a>
Update README.md</li>
<li>See full diff in <a
href="https://github.com/dawidd6/action-download-artifact/compare/v10...v11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dawidd6/action-download-artifact&package-manager=github_actions&previous-version=10&new-version=11)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 21:21:43 +00:00
dependabot[bot]
402cba6f09 chore: CI: bump dcarbone/install-jq-action from 3.1.1 to 3.2.0 (#9138)
Bumps
[dcarbone/install-jq-action](https://github.com/dcarbone/install-jq-action)
from 3.1.1 to 3.2.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dcarbone/install-jq-action/releases">dcarbone/install-jq-action's
releases</a>.</em></p>
<blockquote>
<h2>v3.2.0</h2>
<h2>What's Changed</h2>
<ul>
<li>case sensitive is off by <a
href="https://github.com/Rupreht"><code>@​Rupreht</code></a> in <a
href="https://redirect.github.com/dcarbone/install-jq-action/pull/19">dcarbone/install-jq-action#19</a></li>
<li>Adding 1.8.0 stuff by <a
href="https://github.com/dcarbone"><code>@​dcarbone</code></a> in <a
href="https://redirect.github.com/dcarbone/install-jq-action/pull/20">dcarbone/install-jq-action#20</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Rupreht"><code>@​Rupreht</code></a> made
their first contribution in <a
href="https://redirect.github.com/dcarbone/install-jq-action/pull/19">dcarbone/install-jq-action#19</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/dcarbone/install-jq-action/compare/v3.1.1...v3.2.0">https://github.com/dcarbone/install-jq-action/compare/v3.1.1...v3.2.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b7ef57d46e"><code>b7ef57d</code></a>
Adding 1.8.0 stuff (<a
href="https://redirect.github.com/dcarbone/install-jq-action/issues/20">#20</a>)</li>
<li><a
href="2eac2baa38"><code>2eac2ba</code></a>
case sensitive is off (<a
href="https://redirect.github.com/dcarbone/install-jq-action/issues/19">#19</a>)</li>
<li>See full diff in <a
href="https://github.com/dcarbone/install-jq-action/compare/v3.1.1...v3.2.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dcarbone/install-jq-action&package-manager=github_actions&previous-version=3.1.1&new-version=3.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 21:21:20 +00:00
Cameron Zwarich
c0aad8a27c chore: remove unnecessary special case for Bool (#9136) 2025-07-01 20:42:58 +00:00
Cameron Zwarich
dbcf5b9d9d fix: call lowerEnumToScalarType? with ConstructorVal.induct (#9134)
This PR changes ToIR to call `lowerEnumToScalarType?` with
`ConstructorVal.induct` rather than the name of the constructor itself.
This was an oversight in some refactoring of code in the new compiler
before landing it. It should not affect runtime of compiled code (due to
the extra tagging/untagging being optimized by LLVM), but it does make
IR for the interpreter slightly more efficient.
2025-07-01 20:00:34 +00:00
jrr6
d31dfe92de fix: account for namespaces/open decls in inlineExpr (#9108)
This PR fixes an issue that may have caused inline expressions in
messages to be unnecessarily rendered on a separate line.
2025-07-01 19:28:22 +00:00
Kyle Miller
a018ed3f0f feat: add usedLetOnly to LocalContext binder functions (#9131)
This PR adds a `usedLetOnly` parameter to `LocalContext.mkLambda` and
`LocalContext.mkForall`, to parallel the `MetavarContext` versions.
2025-07-01 18:41:49 +00:00
Leonardo de Moura
535ce0b8fd feat: pow_add normalization in grind (#9133)
This PR adds support for `a^(m+n)` in the `grind` normalizer.
2025-07-01 17:52:16 +00:00
Leonardo de Moura
2bfcb1f25c fix: expand pattern offset gadget in constant patterns (#9130)
This PR fixes unexpected occurrences of the `Grind.offset` gadget in
ground patterns. See new test
2025-07-01 16:31:58 +00:00
Rob23oba
0e5ce1496b fix: pretty-printing of grind syntax (#9128)
This PR fixes spacing in the `grind` attribute and tactic syntax.
Previously `@[grind]` was incorrectly pretty-printed as `@[grind ]`, and
`grind [...] on_failure ...` was pretty-printed `grind [...]on_failure
...`. Fixes that `on_failure` was reserved as keyword.
2025-07-01 16:15:11 +00:00
Eric Wieser
688d9a30d2 fix: incorrectly parenthesized Bool.nots (#9129)
This PR fixes simp lemmas about boolean equalities to say `(!x) = y`
instead of `(!decide (x = y)) = true`

This might be an argument for changing the operator precedence of `!`,
or writing a linter to detect these mistakes.

Zulip thread: [#lean4 > Sum.bnot_isLeft and Sum.bnot_isRight @
💬](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Sum.2Ebnot_isLeft.20and.20Sum.2Ebnot_isRight/near/525938158)
2025-07-01 15:57:14 +00:00
2927 changed files with 23525 additions and 21063 deletions

5
.github/actionlint.yaml vendored Normal file
View File

@@ -0,0 +1,5 @@
self-hosted-runner:
labels:
- nscloud-ubuntu-22.04-amd64-4x16
- nscloud-ubuntu-22.04-amd64-8x16
- nscloud-macos-sonoma-arm64-6x14

View File

@@ -97,14 +97,14 @@ jobs:
sudo apt-get update
sudo apt-get install -y gcc-multilib g++-multilib ccache libuv1-dev:i386 pkgconf:i386
if: matrix.cmultilib
- name: Cache
- name: Restore Cache
id: restore-cache
uses: actions/cache/restore@v4
with:
# NOTE: must be in sync with `save` below
# NOTE: must be in sync with `save` below and with `restore-cache` in `update-stage0.yml`
path: |
.ccache
${{ matrix.name == 'Linux Lake' && false && 'build/stage1/**/*.trace
${{ matrix.name == 'Linux Lake (cached)' && 'build/stage1/**/*.trace
build/stage1/**/*.olean*
build/stage1/**/*.ilean
build/stage1/**/*.ir
@@ -119,9 +119,15 @@ jobs:
run: |
ccache --zero-stats
if: runner.os == 'Linux'
- name: Set up NPROC
- name: Set up env
run: |
echo "NPROC=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)" >> $GITHUB_ENV
if ! diff src/stdlib_flags.h stage0/src/stdlib_flags.h; then
echo "src/stdlib_flags.h and stage0/src/stdlib_flags.h differ, will test and pack stage 2"
echo "TARGET_STAGE=stage2" >> $GITHUB_ENV
else
echo "TARGET_STAGE=stage1" >> $GITHUB_ENV
fi
- name: Build
run: |
ulimit -c unlimited # coredumps
@@ -142,6 +148,9 @@ jobs:
if [[ -n '${{ matrix.prepare-llvm }}' ]]; then
wget -q ${{ matrix.llvm-url }}
PREPARE="$(${{ matrix.prepare-llvm }})"
if [ "$TARGET_STAGE" == "stage2" ]; then
cp -r stage1 stage2
fi
eval "OPTIONS+=($PREPARE)"
fi
if [[ -n '${{ matrix.release }}' && -n '${{ inputs.nightly }}' ]]; then
@@ -156,10 +165,10 @@ jobs:
fi
# contortion to support empty OPTIONS with old macOS bash
cmake .. --preset ${{ matrix.CMAKE_PRESET || 'release' }} -B . ${{ matrix.CMAKE_OPTIONS }} ${OPTIONS[@]+"${OPTIONS[@]}"} -DLEAN_INSTALL_PREFIX=$PWD/..
time make -j$NPROC
time make $TARGET_STAGE -j$NPROC
- name: Install
run: |
make -C build install
make -C build/$TARGET_STAGE install
- name: Check Binaries
run: ${{ matrix.binary-check }} lean-*/bin/* || true
- name: Count binary symbols
@@ -196,12 +205,12 @@ jobs:
id: test
run: |
ulimit -c unlimited # coredumps
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/stage1 -j$NPROC --output-junit test-results.xml ${{ matrix.CTEST_OPTIONS }}
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/$TARGET_STAGE -j$NPROC --output-junit test-results.xml ${{ matrix.CTARGET_OPTIONS }}
if: (matrix.wasm || !matrix.cross) && (inputs.check-level >= 1 || matrix.test)
- name: Test Summary
uses: test-summary/action@v2
with:
paths: build/stage1/test-results.xml
paths: build/${{ env.TARGET_STAGE }}/test-results.xml
# prefix `if` above with `always` so it's run even if tests failed
if: always() && steps.test.conclusion != 'skipped'
- name: Check Test Binary
@@ -226,8 +235,9 @@ jobs:
if: matrix.test-speedcenter
- name: Check rebootstrap
run: |
# clean rebuild in case of Makefile changes
make -C build update-stage0 && rm -rf build/stage* && make -C build -j$NPROC
# clean rebuild in case of Makefile changes/Lake does not detect uncommited stage 0
# changes yet
make -C build update-stage0 && make -C build/stage1 clean-stdlib && make -C build -j$NPROC
if: matrix.check-rebootstrap
- name: CCache stats
if: always()
@@ -246,7 +256,7 @@ jobs:
# NOTE: must be in sync with `restore` above
path: |
.ccache
${{ matrix.name == 'Linux Lake' && false && 'build/stage1/**/*.trace
${{ matrix.name == 'Linux Lake (cached)' && 'build/stage1/**/*.trace
build/stage1/**/*.olean*
build/stage1/**/*.ilean
build/stage1/**/*.ir

View File

@@ -165,7 +165,7 @@ jobs:
{
// portable release build: use channel with older glibc (2.26)
"name": "Linux release",
"os": large && level < 2 ? "nscloud-ubuntu-22.04-amd64-4x16" : "ubuntu-latest",
"os": "ubuntu-latest",
"release": true,
// Special handling for release jobs. We want:
// 1. To run it in PRs so developers get PR toolchains (so secondary is sufficient)
@@ -194,6 +194,13 @@ jobs:
"test-speedcenter": large && level >= 2,
"CMAKE_OPTIONS": "-DUSE_LAKE=ON",
},
{
"name": "Linux Lake (cached)",
"os": "ubuntu-latest",
"check-level": (isPr || isPushToMaster) ? 0 : 2,
"secondary": true,
"CMAKE_OPTIONS": "-DUSE_LAKE=ON",
},
{
"name": "Linux Reldebug",
"os": "ubuntu-latest",
@@ -225,8 +232,8 @@ jobs:
},
{
"name": "macOS aarch64",
// standard GH runner only comes with 7GB so use large runner if possible
"os": large ? "nscloud-macos-sonoma-arm64-6x14" : "macos-14",
// standard GH runner only comes with 7GB so use large runner if possible when running tests
"os": large && !isPr ? "nscloud-macos-sonoma-arm64-6x14" : "macos-14",
"CMAKE_OPTIONS": "-DLEAN_INSTALL_SUFFIX=-darwin_aarch64",
"release": true,
"shell": "bash -euxo pipefail {0}",
@@ -234,13 +241,13 @@ jobs:
"prepare-llvm": "../script/prepare-llvm-macos.sh lean-llvm*",
"binary-check": "otool -L",
"tar": "gtar", // https://github.com/actions/runner-images/issues/2619
// See above for release job levels
// See "Linux release" for release job levels; Grove is not a concern here
"check-level": isPr ? 0 : 2,
"secondary": isPr,
},
{
"name": "Windows",
"os": "windows-2022",
"os": large && level == 2 ? "namespace-profile-windows-amd64-4x16" : "windows-2022",
"release": true,
"check-level": 2,
"shell": "msys2 {0}",
@@ -363,7 +370,7 @@ jobs:
with:
path: artifacts
- name: Release
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
files: artifacts/*/*
fail_on_unmatched_files: true
@@ -407,7 +414,7 @@ jobs:
echo -e "\n*Full commit log*\n" >> diff.md
git log --oneline "$last_tag"..HEAD | sed 's/^/* /' >> diff.md
- name: Release Nightly
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
body_path: diff.md
prerelease: true

View File

@@ -30,8 +30,8 @@ jobs:
# Check if it's a push to master (no PR number and target branch is master)
if [ -z "${{ steps.workflow-info.outputs.pullRequestNumber }}" ]; then
if [ "${{ github.event.workflow_run.head_branch }}" = "master" ]; then
echo "Push to master detected. Skipping for now, to be enabled later."
echo "should-run=false" >> "$GITHUB_OUTPUT"
echo "Push to master detected. Running Grove."
echo "should-run=true" >> "$GITHUB_OUTPUT"
else
echo "Push to non-master branch, skipping"
echo "should-run=false" >> "$GITHUB_OUTPUT"
@@ -40,7 +40,7 @@ jobs:
# Check if it's a PR with grove label
PR_LABELS='${{ steps.workflow-info.outputs.pullRequestLabels }}'
if echo "$PR_LABELS" | grep -q '"grove"'; then
echo "PR with grove label detected"
echo "PR with grove label detected. Running Grove."
echo "should-run=true" >> "$GITHUB_OUTPUT"
else
echo "PR without grove label, skipping"
@@ -51,7 +51,7 @@ jobs:
- name: Fetch upstream invalidated facts
if: ${{ steps.should-run.outputs.should-run == 'true' && steps.workflow-info.outputs.pullRequestNumber != '' }}
id: fetch-upstream
uses: TwoFx/grove-action/fetch-upstream@v0.3
uses: TwoFx/grove-action/fetch-upstream@v0.4
with:
artifact-name: grove-invalidated-facts
base-ref: master
@@ -64,7 +64,7 @@ jobs:
commit: ${{ steps.workflow-info.outputs.sourceHeadSha }}
workflow: ci.yml
path: artifacts
name: build-Linux.*
name: "build-Linux release"
name_is_regexp: true
- name: Unpack toolchain
@@ -95,7 +95,7 @@ jobs:
- name: Build
if: ${{ steps.should-run.outputs.should-run == 'true' }}
id: build
uses: TwoFx/grove-action/build@v0.3
uses: TwoFx/grove-action/build@v0.4
with:
project-path: doc/std/grove
script-name: grove-stdlib

View File

@@ -34,7 +34,7 @@ jobs:
- name: Download artifact from the previous workflow.
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
id: download-artifact
uses: dawidd6/action-download-artifact@v10 # https://github.com/marketplace/actions/download-workflow-artifact
uses: dawidd6/action-download-artifact@v11 # https://github.com/marketplace/actions/download-workflow-artifact
with:
run_id: ${{ github.event.workflow_run.id }}
path: artifacts
@@ -71,7 +71,7 @@ jobs:
GH_TOKEN: ${{ secrets.PR_RELEASES_TOKEN }}
- name: Release (short format)
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
name: Release for PR ${{ steps.workflow-info.outputs.pullRequestNumber }}
# There are coredumps files here as well, but all in deeper subdirectories.
@@ -86,7 +86,7 @@ jobs:
- name: Release (SHA-suffixed format)
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
name: Release for PR ${{ steps.workflow-info.outputs.pullRequestNumber }} (${{ steps.workflow-info.outputs.sourceHeadSha }})
# There are coredumps files here as well, but all in deeper subdirectories.
@@ -151,7 +151,7 @@ jobs:
- name: 'Setup jq'
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: dcarbone/install-jq-action@v3.1.1
uses: dcarbone/install-jq-action@v3.2.0
# Check that the most recently nightly coincides with 'git merge-base HEAD master'
- name: Check merge-base and nightly-testing-YYYY-MM-DD for Mathlib/Batteries

View File

@@ -18,7 +18,7 @@ concurrency:
jobs:
update-stage0:
runs-on: ubuntu-latest
runs-on: nscloud-ubuntu-22.04-amd64-8x16
steps:
# This action should push to an otherwise protected branch, so it
# uses a deploy key with write permissions, as suggested at
@@ -52,6 +52,18 @@ jobs:
run: |
echo "NPROC=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)" >> $GITHUB_ENV
shell: 'nix develop -c bash -euxo pipefail {0}'
- name: Restore Cache
if: env.should_update_stage0 == 'yes'
uses: actions/cache/restore@v4
with:
# NOTE: must be in sync with `restore-cache` in `build-template.yml`
# TODO: actually switch to USE_LAKE once it caches more; for now it just caches more often than any other build type so let's use its cache
path: |
.ccache
key: Linux Lake-build-v3-${{ github.sha }}
# fall back to (latest) previous cache
restore-keys: |
Linux Lake-build-v3
- if: env.should_update_stage0 == 'yes'
run: cmake --preset release
shell: 'nix develop -c bash -euxo pipefail {0}'

View File

@@ -45,3 +45,6 @@
/src/Std/Tactic/BVDecide/ @hargoniX
/src/Lean/Elab/Tactic/BVDecide/ @hargoniX
/src/Std/Sat/ @hargoniX
/src/Std/Do @sgraf812
/src/Std/Tactic/Do @sgraf812
/src/Lean/Elab/Tactic/Do @sgraf812

View File

@@ -1,5 +1,9 @@
import Grove.Framework
import GroveStdlib.Generated.«associative-query-operations»
import GroveStdlib.Generated.«associative-creation-operations»
import GroveStdlib.Generated.«associative-modification-operations»
import GroveStdlib.Generated.«associative-create-then-query»
import GroveStdlib.Generated.«associative-all-operations-covered»
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
@@ -12,3 +16,7 @@ namespace GroveStdlib.Generated
def restoreState : RestoreStateM Unit := do
«associative-query-operations».restoreState
«associative-creation-operations».restoreState
«associative-modification-operations».restoreState
«associative-create-then-query».restoreState
«associative-all-operations-covered».restoreState

View File

@@ -0,0 +1,34 @@
import Grove.Framework
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
conflicts, but be careful.
-/
open Grove.Framework Widget
namespace GroveStdlib.Generated.«associative-all-operations-covered»
def «all-covered» : Assertion.Fact where
widgetId := "associative-all-operations-covered"
factId := "all-covered"
assertionId := "all-covered"
state := {
assertionId := "all-covered"
description := "All operations should be covered"
passed := false
message := "There were 19697 operations that were not covered."
}
metadata := {
status := .bad
comment := "Still missing some!"
}
def table : Assertion.Data where
widgetId := "associative-all-operations-covered"
facts := #[
«all-covered»,
]
def restoreState : RestoreStateM Unit := do
addAssertion table

View File

@@ -0,0 +1,357 @@
import Grove.Framework
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
conflicts, but be careful.
-/
open Grove.Framework Widget
namespace GroveStdlib.Generated.«associative-create-then-query»
def «2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap» : Table.Fact .subexpression .subexpression .declaration where
widgetId := "associative-create-then-query"
factId := "2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap"
rowAssociationId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
columnAssociationId := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
layerStates := #[
{
layerIdentifier := "Std.DHashMap"
rowState :=
some "Std.DHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.emptyWithCapacity,
renderedStatement := "Std.DHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.DHashMap α β",
isDeprecated := false })
columnState :=
some "Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.isEmpty,
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.DHashMap.Raw"
rowState :=
some "Std.DHashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.emptyWithCapacity,
renderedStatement := "Std.DHashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} (capacity : Nat := 8) :\n Std.DHashMap.Raw α β",
isDeprecated := false })
columnState :=
some "Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.isEmpty,
renderedStatement := "Std.DHashMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} (m : Std.DHashMap.Raw α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.ExtDHashMap"
rowState :=
some "Std.ExtDHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.emptyWithCapacity,
renderedStatement := "Std.ExtDHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtDHashMap α β",
isDeprecated := false })
columnState :=
some "Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.isEmpty,
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.DTreeMap"
rowState :=
some "Std.DTreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.empty,
renderedStatement := "Std.DTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.DTreeMap α β cmp",
isDeprecated := false })
columnState :=
some "Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.isEmpty,
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.DTreeMap.Raw"
rowState :=
some "Std.DTreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.empty,
renderedStatement := "Std.DTreeMap.Raw.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.DTreeMap.Raw α β cmp",
isDeprecated := false })
columnState :=
some "Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.isEmpty,
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.ExtDTreeMap"
rowState :=
some "Std.ExtDTreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.empty,
renderedStatement := "Std.ExtDTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.ExtDTreeMap α β cmp",
isDeprecated := false })
columnState :=
some "Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.isEmpty,
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
]
metadata := {
status := .done
comment := "Not necessary for `ExtDHashMap` because of simp lemma turning into varno"
}
def «5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap» : Table.Fact .subexpression .subexpression .declaration where
widgetId := "associative-create-then-query"
factId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap"
rowAssociationId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnAssociationId := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
layerStates := #[
{
layerIdentifier := "Std.DHashMap"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", displayShort := "" }
columnState :=
some "Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.isEmpty,
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
"Std.DHashMap.isEmpty_empty", Grove.Framework.Declaration.thm
{ name := `Std.DHashMap.isEmpty_empty,
renderedStatement := "Std.DHashMap.isEmpty_empty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} :\n ∅.isEmpty = true",
isSimp := true,
isDeprecated := false }
,
]
},
{
layerIdentifier := "Std.DHashMap.Raw"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", displayShort := "" }
columnState :=
some "Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.isEmpty,
renderedStatement := "Std.DHashMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} (m : Std.DHashMap.Raw α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
"Std.DHashMap.Raw.isEmpty_emptyc", Grove.Framework.Declaration.thm
{ name := `Std.DHashMap.Raw.isEmpty_emptyc,
renderedStatement := "Std.DHashMap.Raw.isEmpty_emptyc.{u_1, u_2} {α : Type u_1} {β : α → Type u_2} [BEq α] [Hashable α] :\n ∅.isEmpty = true",
isSimp := false,
isDeprecated := true }
,
]
},
{
layerIdentifier := "Std.ExtDHashMap"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", displayShort := "" }
columnState :=
some "Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.isEmpty,
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.DTreeMap"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", displayShort := "" }
columnState :=
some "Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.isEmpty,
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
"Std.DTreeMap.isEmpty_emptyc", Grove.Framework.Declaration.thm
{ name := `Std.DTreeMap.isEmpty_emptyc,
renderedStatement := "Std.DTreeMap.isEmpty_emptyc.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n ∅.isEmpty = true",
isSimp := true,
isDeprecated := false }
,
]
},
{
layerIdentifier := "Std.DTreeMap.Raw"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", displayShort := "" }
columnState :=
some "Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.isEmpty,
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
"Std.DTreeMap.Raw.isEmpty_emptyc", Grove.Framework.Declaration.thm
{ name := `Std.DTreeMap.Raw.isEmpty_emptyc,
renderedStatement := "Std.DTreeMap.Raw.isEmpty_emptyc.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n ∅.isEmpty = true",
isSimp := true,
isDeprecated := false }
,
]
},
{
layerIdentifier := "Std.ExtDTreeMap"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", displayShort := "" }
columnState :=
some "Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.isEmpty,
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
"Std.ExtDTreeMap.isEmpty_empty", Grove.Framework.Declaration.thm
{ name := `Std.ExtDTreeMap.isEmpty_empty,
renderedStatement := "Std.ExtDTreeMap.isEmpty_empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n ∅.isEmpty = true",
isSimp := true,
isDeprecated := false }
,
]
},
]
metadata := {
status := .bad
comment := "Missing for `ExtDHashMap`"
}
def table : Table.Data .subexpression .subexpression .declaration where
widgetId := "associative-create-then-query"
selectedRowAssociations := #["2cb3c441-9663-4ce7-9527-0f40fc29925a", "7743a485-024d-43b6-bd5f-ebd3182eb94d", "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d", ]
selectedColumnAssociations := #["01f88623-fa5f-4380-9772-b30f2fec5c94", "f084f852-af71-45b6-8ab3-d251a8144f72", ]
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
selectedCellOptions := #[
{
layerIdentifier := "Std.DHashMap"
rowValue := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DHashMap.isEmpty_emptyWithCapacity", ]
},
{
layerIdentifier := "Std.DHashMap.Raw"
rowValue := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DHashMap.Raw.isEmpty_emptyWithCapacity", ]
},
{
layerIdentifier := "Std.DHashMap"
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DHashMap.isEmpty_empty", ]
},
{
layerIdentifier := "Std.DHashMap.Raw"
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DHashMap.Raw.isEmpty_emptyc", ]
},
{
layerIdentifier := "Std.DTreeMap"
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DTreeMap.isEmpty_emptyc", ]
},
{
layerIdentifier := "Std.DTreeMap.Raw"
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DTreeMap.Raw.isEmpty_emptyc", ]
},
{
layerIdentifier := "Std.ExtDTreeMap"
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.ExtDTreeMap.isEmpty_empty", ]
},
]
facts := #[
«2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap»,
«5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap»,
]
def restoreState : RestoreStateM Unit := do
addTable table

View File

@@ -0,0 +1,216 @@
import Grove.Framework
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
conflicts, but be careful.
-/
open Grove.Framework Widget
namespace GroveStdlib.Generated.«associative-creation-operations»
def «2cb3c441-9663-4ce7-9527-0f40fc29925a» : AssociationTable.Fact .subexpression where
widgetId := "associative-creation-operations"
factId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
rowId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
rowState := #["Std.DHashMap", "Std.DHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.emptyWithCapacity,
renderedStatement := "Std.DHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.DHashMap α β",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.emptyWithCapacity,
renderedStatement := "Std.DHashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} (capacity : Nat := 8) :\n Std.DHashMap.Raw α β",
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.emptyWithCapacity,
renderedStatement := "Std.ExtDHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtDHashMap α β",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.empty,
renderedStatement := "Std.DTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.DTreeMap α β cmp",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.empty,
renderedStatement := "Std.DTreeMap.Raw.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.DTreeMap.Raw α β cmp",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.empty,
renderedStatement := "Std.ExtDTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.ExtDTreeMap α β cmp",
isDeprecated := false }),"Std.HashMap", "Std.HashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.emptyWithCapacity,
renderedStatement := "Std.HashMap.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.HashMap α β",
isDeprecated := false }),"Std.HashMap.Raw", "Std.HashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.Raw.emptyWithCapacity,
renderedStatement := "Std.HashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} (capacity : Nat := 8) :\n Std.HashMap.Raw α β",
isDeprecated := false }),"Std.ExtHashMap", "Std.ExtHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashMap.emptyWithCapacity,
renderedStatement := "Std.ExtHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtHashMap α β",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.empty,
renderedStatement := "Std.TreeMap.empty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} : Std.TreeMap α β cmp",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.empty,
renderedStatement := "Std.TreeMap.Raw.empty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} :\n Std.TreeMap.Raw α β cmp",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.empty,
renderedStatement := "Std.ExtTreeMap.empty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} :\n Std.ExtTreeMap α β cmp",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.emptyWithCapacity,
renderedStatement := "Std.HashSet.emptyWithCapacity.{u} {α : Type u} [BEq α] [Hashable α] (capacity : Nat := 8) :\n Std.HashSet α",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.emptyWithCapacity,
renderedStatement := "Std.HashSet.Raw.emptyWithCapacity.{u} {α : Type u} (capacity : Nat := 8) : Std.HashSet.Raw α",
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.emptyWithCapacity,
renderedStatement := "Std.ExtHashSet.emptyWithCapacity.{u} {α : Type u} [BEq α] [Hashable α] (capacity : Nat := 8) :\n Std.ExtHashSet α",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.empty,
renderedStatement := "Std.TreeSet.empty.{u} {α : Type u} {cmp : αα → Ordering} : Std.TreeSet α cmp",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.empty,
renderedStatement := "Std.TreeSet.Raw.empty.{u} {α : Type u} {cmp : αα → Ordering} : Std.TreeSet.Raw α cmp",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.empty,
renderedStatement := "Std.ExtTreeSet.empty.{u} {α : Type u} {cmp : αα → Ordering} : Std.ExtTreeSet α cmp",
isDeprecated := false }),]
metadata := {
status := .done
comment := ""
}
def «7743a485-024d-43b6-bd5f-ebd3182eb94d» : AssociationTable.Fact .subexpression where
widgetId := "associative-creation-operations"
factId := "7743a485-024d-43b6-bd5f-ebd3182eb94d"
rowId := "7743a485-024d-43b6-bd5f-ebd3182eb94d"
rowState := #["Std.DHashMap", "Std.DHashMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.ofList,
renderedStatement := "Std.DHashMap.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.DHashMap α β",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.ofList,
renderedStatement := "Std.DHashMap.Raw.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.DHashMap.Raw α β",
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.ofList,
renderedStatement := "Std.ExtDHashMap.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.ExtDHashMap α β",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.ofList,
renderedStatement := "Std.DTreeMap.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : αα → Ordering := by exact compare) : Std.DTreeMap α β cmp",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.ofList,
renderedStatement := "Std.DTreeMap.Raw.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : αα → Ordering := by exact compare) : Std.DTreeMap.Raw α β cmp",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.ofList,
renderedStatement := "Std.ExtDTreeMap.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : αα → Ordering := by exact compare) : Std.ExtDTreeMap α β cmp",
isDeprecated := false }),"Std.HashMap", "Std.HashMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.ofList,
renderedStatement := "Std.HashMap.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.HashMap α β",
isDeprecated := false }),"Std.HashMap.Raw", "Std.HashMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.Raw.ofList,
renderedStatement := "Std.HashMap.Raw.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.HashMap.Raw α β",
isDeprecated := false }),"Std.ExtHashMap", "Std.ExtHashMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashMap.ofList,
renderedStatement := "Std.ExtHashMap.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.ExtHashMap α β",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.ofList,
renderedStatement := "Std.TreeMap.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : αα → Ordering := by exact compare) : Std.TreeMap α β cmp",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.ofList,
renderedStatement := "Std.TreeMap.Raw.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : αα → Ordering := by exact compare) : Std.TreeMap.Raw α β cmp",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.ofList,
renderedStatement := "Std.ExtTreeMap.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : αα → Ordering := by exact compare) : Std.ExtTreeMap α β cmp",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.ofList,
renderedStatement := "Std.HashSet.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.HashSet α",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.ofList,
renderedStatement := "Std.HashSet.Raw.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.HashSet.Raw α",
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.ofList,
renderedStatement := "Std.ExtHashSet.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.ExtHashSet α",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.ofList,
renderedStatement := "Std.TreeSet.ofList.{u} {α : Type u} (l : List α) (cmp : αα → Ordering := by exact compare) :\n Std.TreeSet α cmp",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.ofList,
renderedStatement := "Std.TreeSet.Raw.ofList.{u} {α : Type u} (l : List α) (cmp : αα → Ordering := by exact compare) :\n Std.TreeSet.Raw α cmp",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.ofList,
renderedStatement := "Std.ExtTreeSet.ofList.{u} {α : Type u} (l : List α) (cmp : αα → Ordering := by exact compare) :\n Std.ExtTreeSet α cmp",
isDeprecated := false }),]
metadata := {
status := .done
comment := ""
}
def «5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d» : AssociationTable.Fact .subexpression where
widgetId := "associative-creation-operations"
factId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
rowId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
rowState := #["Std.DHashMap", "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", displayShort := "" },"Std.DHashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", displayShort := "" },"Std.ExtDHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", displayShort := "" },"Std.DTreeMap", "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", displayShort := "" },"Std.DTreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", displayShort := "" },"Std.ExtDTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", displayShort := "" },"Std.HashMap", "app (EmptyCollection.emptyCollection) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.HashMap*)", displayShort := "" },"Std.HashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)", displayShort := "" },"Std.ExtHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)", displayShort := "" },"Std.TreeMap", "app (EmptyCollection.emptyCollection) (Std.TreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeMap*)", displayShort := "" },"Std.TreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)", displayShort := "" },"Std.ExtTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)", displayShort := "" },"Std.HashSet", "app (EmptyCollection.emptyCollection) (Std.HashSet*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.HashSet*)", displayShort := "" },"Std.HashSet.Raw", "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)", displayShort := "" },"Std.ExtHashSet", "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)", displayShort := "" },"Std.TreeSet", "app (EmptyCollection.emptyCollection) (Std.TreeSet*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeSet*)", displayShort := "" },"Std.TreeSet.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)", displayShort := "" },"Std.ExtTreeSet", "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)", displayShort := "" },]
metadata := {
status := .done
comment := ""
}
def table : AssociationTable.Data .subexpression where
widgetId := "associative-creation-operations"
rows := #[
"2cb3c441-9663-4ce7-9527-0f40fc29925a", "empty", #["Std.DHashMap", "Std.DHashMap.emptyWithCapacity","Std.DHashMap.Raw", "Std.DHashMap.Raw.emptyWithCapacity","Std.ExtDHashMap", "Std.ExtDHashMap.emptyWithCapacity","Std.DTreeMap", "Std.DTreeMap.empty","Std.DTreeMap.Raw", "Std.DTreeMap.Raw.empty","Std.ExtDTreeMap", "Std.ExtDTreeMap.empty","Std.HashMap", "Std.HashMap.emptyWithCapacity","Std.HashMap.Raw", "Std.HashMap.Raw.emptyWithCapacity","Std.ExtHashMap", "Std.ExtHashMap.emptyWithCapacity","Std.TreeMap", "Std.TreeMap.empty","Std.TreeMap.Raw", "Std.TreeMap.Raw.empty","Std.ExtTreeMap", "Std.ExtTreeMap.empty","Std.HashSet", "Std.HashSet.emptyWithCapacity","Std.HashSet.Raw", "Std.HashSet.Raw.emptyWithCapacity","Std.ExtHashSet", "Std.ExtHashSet.emptyWithCapacity","Std.TreeSet", "Std.TreeSet.empty","Std.TreeSet.Raw", "Std.TreeSet.Raw.empty","Std.ExtTreeSet", "Std.ExtTreeSet.empty",],
"7743a485-024d-43b6-bd5f-ebd3182eb94d", "ofList", #["Std.DHashMap", "Std.DHashMap.ofList","Std.DHashMap.Raw", "Std.DHashMap.Raw.ofList","Std.ExtDHashMap", "Std.ExtDHashMap.ofList","Std.DTreeMap", "Std.DTreeMap.ofList","Std.DTreeMap.Raw", "Std.DTreeMap.Raw.ofList","Std.ExtDTreeMap", "Std.ExtDTreeMap.ofList","Std.HashMap", "Std.HashMap.ofList","Std.HashMap.Raw", "Std.HashMap.Raw.ofList","Std.ExtHashMap", "Std.ExtHashMap.ofList","Std.TreeMap", "Std.TreeMap.ofList","Std.TreeMap.Raw", "Std.TreeMap.Raw.ofList","Std.ExtTreeMap", "Std.ExtTreeMap.ofList","Std.HashSet", "Std.HashSet.ofList","Std.HashSet.Raw", "Std.HashSet.Raw.ofList","Std.ExtHashSet", "Std.ExtHashSet.ofList","Std.TreeSet", "Std.TreeSet.ofList","Std.TreeSet.Raw", "Std.TreeSet.Raw.ofList","Std.ExtTreeSet", "Std.ExtTreeSet.ofList",],
"5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d", "emptyCollection", #["Std.DHashMap", "app (EmptyCollection.emptyCollection) (Std.DHashMap*)","Std.DHashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)","Std.ExtDHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)","Std.DTreeMap", "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)","Std.DTreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)","Std.ExtDTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)","Std.HashMap", "app (EmptyCollection.emptyCollection) (Std.HashMap*)","Std.HashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)","Std.ExtHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)","Std.TreeMap", "app (EmptyCollection.emptyCollection) (Std.TreeMap*)","Std.TreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)","Std.ExtTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)","Std.HashSet", "app (EmptyCollection.emptyCollection) (Std.HashSet*)","Std.HashSet.Raw", "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)","Std.ExtHashSet", "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)","Std.TreeSet", "app (EmptyCollection.emptyCollection) (Std.TreeSet*)","Std.TreeSet.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)","Std.ExtTreeSet", "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)",],
]
facts := #[
«2cb3c441-9663-4ce7-9527-0f40fc29925a»,
«7743a485-024d-43b6-bd5f-ebd3182eb94d»,
«5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d»,
]
def restoreState : RestoreStateM Unit := do
addAssociationTable table

View File

@@ -0,0 +1,21 @@
import Grove.Framework
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
conflicts, but be careful.
-/
open Grove.Framework Widget
namespace GroveStdlib.Generated.«associative-modification-operations»
def table : AssociationTable.Data .subexpression where
widgetId := "associative-modification-operations"
rows := #[
]
facts := #[
]
def restoreState : RestoreStateM Unit := do
addAssociationTable table

View File

@@ -16,7 +16,7 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
rowState := #["Std.DHashMap", "Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.isEmpty,
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.DHashMap α β) : Bool",
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.isEmpty,
@@ -24,23 +24,23 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.isEmpty,
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.isEmpty,
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} (t : Std.DTreeMap α β cmp) : Bool",
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.isEmpty,
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} (t : Std.DTreeMap.Raw α β cmp) :\n Bool",
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.isEmpty,
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} (t : Std.ExtDTreeMap α β cmp) :\n Bool",
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
isDeprecated := false }),"Std.HashMap", "Std.HashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.isEmpty,
renderedStatement := "Std.HashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashMap α β) : Bool",
renderedStatement := "Std.HashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) : Bool",
isDeprecated := false }),"Std.HashMap.Raw", "Std.HashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.Raw.isEmpty,
@@ -48,19 +48,19 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
isDeprecated := false }),"Std.ExtHashMap", "Std.ExtHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashMap.isEmpty,
renderedStatement := "Std.ExtHashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) : Bool",
renderedStatement := "Std.ExtHashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) : Bool",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.isEmpty,
renderedStatement := "Std.TreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp) : Bool",
renderedStatement := "Std.TreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap α β cmp) : Bool",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.isEmpty,
renderedStatement := "Std.TreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap.Raw α β cmp) : Bool",
renderedStatement := "Std.TreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap.Raw α β cmp) : Bool",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.isEmpty,
renderedStatement := "Std.ExtTreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.ExtTreeMap α β cmp) : Bool",
renderedStatement := "Std.ExtTreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.ExtTreeMap α β cmp) : Bool",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.isEmpty,
@@ -72,7 +72,7 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.isEmpty,
renderedStatement := "Std.ExtHashSet.isEmpty.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) : Bool",
renderedStatement := "Std.ExtHashSet.isEmpty.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashSet α) : Bool",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.isEmpty,
@@ -97,7 +97,7 @@ def «f084f852-af71-45b6-8ab3-d251a8144f72» : AssociationTable.Fact .subexpress
rowState := #["Std.DHashMap", "Std.DHashMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.size,
renderedStatement := "Std.DHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.DHashMap α β) : Nat",
renderedStatement := "Std.DHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Nat",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.size,
@@ -105,23 +105,23 @@ def «f084f852-af71-45b6-8ab3-d251a8144f72» : AssociationTable.Fact .subexpress
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.size,
renderedStatement := "Std.ExtDHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtDHashMap α β) : Nat",
renderedStatement := "Std.ExtDHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Nat",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.size,
renderedStatement := "Std.DTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} (t : Std.DTreeMap α β cmp) : Nat",
renderedStatement := "Std.DTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) : Nat",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.size,
renderedStatement := "Std.DTreeMap.Raw.size.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} (t : Std.DTreeMap.Raw α β cmp) : Nat",
renderedStatement := "Std.DTreeMap.Raw.size.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Nat",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.size,
renderedStatement := "Std.ExtDTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} (t : Std.ExtDTreeMap α β cmp) : Nat",
renderedStatement := "Std.ExtDTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Nat",
isDeprecated := false }),"Std.HashMap", "Std.HashMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.size,
renderedStatement := "Std.HashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashMap α β) : Nat",
renderedStatement := "Std.HashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) : Nat",
isDeprecated := false }),"Std.HashMap.Raw", "Std.HashMap.Raw.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.Raw.size,
@@ -129,19 +129,19 @@ def «f084f852-af71-45b6-8ab3-d251a8144f72» : AssociationTable.Fact .subexpress
isDeprecated := false }),"Std.ExtHashMap", "Std.ExtHashMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashMap.size,
renderedStatement := "Std.ExtHashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) : Nat",
renderedStatement := "Std.ExtHashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) : Nat",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.size,
renderedStatement := "Std.TreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp) : Nat",
renderedStatement := "Std.TreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap α β cmp) : Nat",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.size,
renderedStatement := "Std.TreeMap.Raw.size.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap.Raw α β cmp) : Nat",
renderedStatement := "Std.TreeMap.Raw.size.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap.Raw α β cmp) : Nat",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.size,
renderedStatement := "Std.ExtTreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.ExtTreeMap α β cmp) : Nat",
renderedStatement := "Std.ExtTreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.ExtTreeMap α β cmp) : Nat",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.size,
@@ -178,11 +178,11 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
rowState := #["Std.DTreeMap", "Std.DTreeMap.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.any,
renderedStatement := "Std.DTreeMap.any.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} (t : Std.DTreeMap α β cmp)\n (p : (a : α) → β a → Bool) : Bool",
renderedStatement := "Std.DTreeMap.any.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.any,
renderedStatement := "Std.DTreeMap.Raw.any.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} (t : Std.DTreeMap.Raw α β cmp)\n (p : (a : α) → β a → Bool) : Bool",
renderedStatement := "Std.DTreeMap.Raw.any.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.any,
@@ -190,11 +190,11 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.any,
renderedStatement := "Std.TreeMap.any.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp) (p : α → β → Bool) :\n Bool",
renderedStatement := "Std.TreeMap.any.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp)\n (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.any,
renderedStatement := "Std.TreeMap.Raw.any.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap.Raw α β cmp)\n (p : α → β → Bool) : Bool",
renderedStatement := "Std.TreeMap.Raw.any.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.any,
@@ -202,7 +202,7 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
isDeprecated := false }),"Std.HashSet", "Std.HashSet.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.any,
renderedStatement := "Std.HashSet.any.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α) (p : α → Bool) : Bool",
renderedStatement := "Std.HashSet.any.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α)\n (p : α → Bool) : Bool",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.any,
@@ -210,15 +210,15 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.any,
renderedStatement := "Std.TreeSet.any.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) : Bool",
renderedStatement := "Std.TreeSet.any.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) :\n Bool",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.any,
renderedStatement := "Std.TreeSet.Raw.any.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp) (p : α → Bool) : Bool",
renderedStatement := "Std.TreeSet.Raw.any.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp)\n (p : α → Bool) : Bool",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.any,
renderedStatement := "Std.ExtTreeSet.any.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp)\n (p : α → Bool) : Bool",
renderedStatement := "Std.ExtTreeSet.any.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (p : α → Bool) : Bool",
isDeprecated := false }),]
metadata := {
status := .bad
@@ -228,62 +228,51 @@ def «c1d181f6-3204-4956-946f-e81619f9feb4» : AssociationTable.Fact .subexpress
widgetId := "associative-query-operations"
factId := "c1d181f6-3204-4956-946f-e81619f9feb4"
rowId := "c1d181f6-3204-4956-946f-e81619f9feb4"
rowState := #["Std.DTreeMap", "Std.DTreeMap.all", .declaration (Declaration.def {
name := `Std.DTreeMap.all
renderedStatement := "Std.DTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} (t : Std.DTreeMap α β cmp)\n (p : (a : α) → β a → Bool) : Bool"
isDeprecated := false
}
),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.all", .declaration (Declaration.def {
name := `Std.DTreeMap.Raw.all
renderedStatement := "Std.DTreeMap.Raw.all.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} (t : Std.DTreeMap.Raw α β cmp)\n (p : (a : α) → β a → Bool) : Bool"
isDeprecated := false
}
),"Std.ExtDTreeMap", "Std.ExtDTreeMap.all", .declaration (Declaration.def {
name := `Std.ExtDTreeMap.all
renderedStatement := "Std.ExtDTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtDTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool"
isDeprecated := false
}
),"Std.TreeMap", "Std.TreeMap.all", .declaration (Declaration.def {
name := `Std.TreeMap.all
renderedStatement := "Std.TreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp) (p : α → β → Bool) :\n Bool"
isDeprecated := false
}
),"Std.TreeMap.Raw", "Std.TreeMap.Raw.all", .declaration (Declaration.def {
name := `Std.TreeMap.Raw.all
renderedStatement := "Std.TreeMap.Raw.all.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap.Raw α β cmp)\n (p : α → β → Bool) : Bool"
isDeprecated := false
}
),"Std.ExtTreeMap", "Std.ExtTreeMap.all", .declaration (Declaration.def {
name := `Std.ExtTreeMap.all
renderedStatement := "Std.ExtTreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (p : α β → Bool) : Bool"
isDeprecated := false
}
),"Std.HashSet", "Std.HashSet.all", .declaration (Declaration.def {
name := `Std.HashSet.all
renderedStatement := "Std.HashSet.all.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α) (p : α → Bool) : Bool"
isDeprecated := false
}
),"Std.HashSet.Raw", "Std.HashSet.Raw.all", .declaration (Declaration.def {
name := `Std.HashSet.Raw.all
renderedStatement := "Std.HashSet.Raw.all.{u} {α : Type u} (m : Std.HashSet.Raw α) (p : α → Bool) : Bool"
isDeprecated := false
}
),"Std.TreeSet", "Std.TreeSet.all", .declaration (Declaration.def {
name := `Std.TreeSet.all
renderedStatement := "Std.TreeSet.all.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) : Bool"
isDeprecated := false
}
),"Std.TreeSet.Raw", "Std.TreeSet.Raw.all", .declaration (Declaration.def {
name := `Std.TreeSet.Raw.all
renderedStatement := "Std.TreeSet.Raw.all.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp) (p : α → Bool) : Bool"
isDeprecated := false
}
),"Std.ExtTreeSet", "Std.ExtTreeSet.all", .declaration (Declaration.def {
name := `Std.ExtTreeSet.all
renderedStatement := "Std.ExtTreeSet.all.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp)\n (p : α → Bool) : Bool"
isDeprecated := false
}
),]
rowState := #["Std.DTreeMap", "Std.DTreeMap.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.all,
renderedStatement := "Std.DTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.all,
renderedStatement := "Std.DTreeMap.Raw.all.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.all,
renderedStatement := "Std.ExtDTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtDTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.all,
renderedStatement := "Std.TreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp)\n (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.all,
renderedStatement := "Std.TreeMap.Raw.all.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.all,
renderedStatement := "Std.ExtTreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.all,
renderedStatement := "Std.HashSet.all.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α)\n (p : α → Bool) : Bool",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.all,
renderedStatement := "Std.HashSet.Raw.all.{u} {α : Type u} (m : Std.HashSet.Raw α) (p : α → Bool) : Bool",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.all,
renderedStatement := "Std.TreeSet.all.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) :\n Bool",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.all,
renderedStatement := "Std.TreeSet.Raw.all.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp)\n (p : α → Bool) : Bool",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.all,
renderedStatement := "Std.ExtTreeSet.all.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (p : α → Bool) : Bool",
isDeprecated := false }),]
metadata := {
status := .bad
comment := "Missing for some containers"
@@ -292,97 +281,79 @@ def «efe57f41-7db7-4303-b3a6-5216a70c43ce» : AssociationTable.Fact .subexpress
widgetId := "associative-query-operations"
factId := "efe57f41-7db7-4303-b3a6-5216a70c43ce"
rowId := "efe57f41-7db7-4303-b3a6-5216a70c43ce"
rowState := #["Std.DHashMap", "Std.DHashMap.getD", .declaration (Declaration.def {
name := `Std.DHashMap.getD
renderedStatement := "Std.DHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (fallback : β a) : β a"
isDeprecated := false
}
),"Std.DHashMap.Raw", "Std.DHashMap.Raw.getD", .declaration (Declaration.def {
name := `Std.DHashMap.Raw.getD
renderedStatement := "Std.DHashMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α] [LawfulBEq α] (m : Std.DHashMap.Raw α β)\n (a : α) (fallback : β a) : β a"
isDeprecated := false
}
),"Std.ExtDHashMap", "Std.ExtDHashMap.getD", .declaration (Declaration.def {
name := `Std.ExtDHashMap.getD
renderedStatement := "Std.ExtDHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.ExtDHashMap α β) (a : α) (fallback : β a) : β a"
isDeprecated := false
}
),"Std.DTreeMap", "Std.DTreeMap.getD", .declaration (Declaration.def {
name := `Std.DTreeMap.getD
renderedStatement := "Std.DTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap α β cmp) (a : α) (fallback : β a) : β a"
isDeprecated := false
}
),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.getD", .declaration (Declaration.def {
name := `Std.DTreeMap.Raw.getD
renderedStatement := "Std.DTreeMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap.Raw α β cmp) (a : α) (fallback : β a) : β a"
isDeprecated := false
}
),"Std.ExtDTreeMap", "Std.ExtDTreeMap.getD", .declaration (Declaration.def {
name := `Std.ExtDTreeMap.getD
renderedStatement := "Std.ExtDTreeMap.getD.{u, v} {α : Type u} {β : α Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (fallback : β a) : β a"
isDeprecated := false
}
),"Std.HashMap", "Std.HashMap.getD", .declaration (Declaration.def {
name := `Std.HashMap.getD
renderedStatement := "Std.HashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashMap α β) (a : α)\n (fallback : β) : β"
isDeprecated := false
}
),"Std.HashMap.Raw", "Std.HashMap.Raw.getD", .declaration (Declaration.def {
name := `Std.HashMap.Raw.getD
renderedStatement := "Std.HashMap.Raw.getD.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : Std.HashMap.Raw α β) (a : α)\n (fallback : β) : β"
isDeprecated := false
}
),"Std.ExtHashMap", "Std.ExtHashMap.getD", .declaration (Declaration.def {
name := `Std.ExtHashMap.getD
renderedStatement := "Std.ExtHashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) (a : α) (fallback : β) : β"
isDeprecated := false
}
),"Std.TreeMap", "Std.TreeMap.getD", .declaration (Declaration.def {
name := `Std.TreeMap.getD
renderedStatement := "Std.TreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp) (a : α)\n (fallback : β) : β"
isDeprecated := false
}
),"Std.TreeMap.Raw", "Std.TreeMap.Raw.getD", .declaration (Declaration.def {
name := `Std.TreeMap.Raw.getD
renderedStatement := "Std.TreeMap.Raw.getD.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap.Raw α β cmp) (a : α)\n (fallback : β) : β"
isDeprecated := false
}
),"Std.ExtTreeMap", "Std.ExtTreeMap.getD", .declaration (Declaration.def {
name := `Std.ExtTreeMap.getD
renderedStatement := "Std.ExtTreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (a : α) (fallback : β) : β"
isDeprecated := false
}
),"Std.HashSet", "Std.HashSet.getD", .declaration (Declaration.def {
name := `Std.HashSet.getD
renderedStatement := "Std.HashSet.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a fallback : α) : α"
isDeprecated := false
}
),"Std.HashSet.Raw", "Std.HashSet.Raw.getD", .declaration (Declaration.def {
name := `Std.HashSet.Raw.getD
renderedStatement := "Std.HashSet.Raw.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α) (a fallback : α) : α"
isDeprecated := false
}
),"Std.ExtHashSet", "Std.ExtHashSet.getD", .declaration (Declaration.def {
name := `Std.ExtHashSet.getD
renderedStatement := "Std.ExtHashSet.getD.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a fallback : α) : α"
isDeprecated := false
}
),"Std.TreeSet", "Std.TreeSet.getD", .declaration (Declaration.def {
name := `Std.TreeSet.getD
renderedStatement := "Std.TreeSet.getD.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) (a fallback : α) : α"
isDeprecated := false
}
),"Std.TreeSet.Raw", "Std.TreeSet.Raw.getD", .declaration (Declaration.def {
name := `Std.TreeSet.Raw.getD
renderedStatement := "Std.TreeSet.Raw.getD.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp) (a fallback : α) : α"
isDeprecated := false
}
),"Std.ExtTreeSet", "Std.ExtTreeSet.getD", .declaration (Declaration.def {
name := `Std.ExtTreeSet.getD
renderedStatement := "Std.ExtTreeSet.getD.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp)\n (a fallback : α) : α"
isDeprecated := false
}
),]
rowState := #["Std.DHashMap", "Std.DHashMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.getD,
renderedStatement := "Std.DHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (fallback : β a) : β a",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.getD,
renderedStatement := "Std.DHashMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α] [LawfulBEq α]\n (m : Std.DHashMap.Raw α β) (a : α) (fallback : β a) : β a",
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.getD,
renderedStatement := "Std.ExtDHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [LawfulBEq α] (m : Std.ExtDHashMap α β) (a : α) (fallback : β a) : β a",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.getD,
renderedStatement := "Std.DTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap α β cmp) (a : α) (fallback : β a) : β a",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.getD,
renderedStatement := "Std.DTreeMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap.Raw α β cmp) (a : α) (fallback : β a) : β a",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.getD,
renderedStatement := "Std.ExtDTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n [Std.TransCmp cmp] [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (fallback : β a) :\n β a",
isDeprecated := false }),"Std.HashMap", "Std.HashMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.getD,
renderedStatement := "Std.HashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.HashMap.Raw", "Std.HashMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.Raw.getD,
renderedStatement := "Std.HashMap.Raw.getD.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : Std.HashMap.Raw α β)\n (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.ExtHashMap", "Std.ExtHashMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashMap.getD,
renderedStatement := "Std.ExtHashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.getD,
renderedStatement := "Std.TreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp)\n (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.getD,
renderedStatement := "Std.TreeMap.Raw.getD.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.getD,
renderedStatement := "Std.ExtTreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.getD,
renderedStatement := "Std.HashSet.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a fallback : α) : α",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.getD,
renderedStatement := "Std.HashSet.Raw.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α)\n (a fallback : α) : α",
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.getD,
renderedStatement := "Std.ExtHashSet.getD.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a fallback : α) : α",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.getD,
renderedStatement := "Std.TreeSet.getD.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp)\n (a fallback : α) : α",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.getD,
renderedStatement := "Std.TreeSet.Raw.getD.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp)\n (a fallback : α) : α",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.getD,
renderedStatement := "Std.ExtTreeSet.getD.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (a fallback : α) : α",
isDeprecated := false }),]
metadata := {
status := .done
comment := ""
@@ -391,73 +362,61 @@ def «e23b1119-3b57-433e-a68d-68fd70b9943d» : AssociationTable.Fact .subexpress
widgetId := "associative-query-operations"
factId := "e23b1119-3b57-433e-a68d-68fd70b9943d"
rowId := "e23b1119-3b57-433e-a68d-68fd70b9943d"
rowState := #["Std.DHashMap", "Std.DHashMap.get", .declaration (Declaration.def {
name := `Std.DHashMap.get
renderedStatement := "Std.DHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (h : a ∈ m) : β a"
isDeprecated := false
}
),"Std.DHashMap.Raw", "Std.DHashMap.Raw.Const.get", .declaration (Declaration.def {
name := `Std.DHashMap.Raw.Const.get
renderedStatement := "Std.DHashMap.Raw.Const.get.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : Std.DHashMap.Raw α fun x => β)\n (a : α) (h : a ∈ m) : β"
isDeprecated := false
}
),"Std.ExtDHashMap", "Std.ExtDHashMap.get", .declaration (Declaration.def {
name := `Std.ExtDHashMap.get
renderedStatement := "Std.ExtDHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.ExtDHashMap α β) (a : α) (h : a ∈ m) : β a"
isDeprecated := false
}
),"Std.DTreeMap", "Std.DTreeMap.get", .declaration (Declaration.def {
name := `Std.DTreeMap.get
renderedStatement := "Std.DTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap α β cmp) (a : α) (h : a ∈ t) : β a"
isDeprecated := false
}
),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.get", .declaration (Declaration.def {
name := `Std.DTreeMap.Raw.get
renderedStatement := "Std.DTreeMap.Raw.get.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap.Raw α β cmp) (a : α) (h : a ∈ t) : β a"
isDeprecated := false
}
),"Std.ExtDTreeMap", "Std.ExtDTreeMap.get", .declaration (Declaration.def {
name := `Std.ExtDTreeMap.get
renderedStatement := "Std.ExtDTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (h : a ∈ t) : β a"
isDeprecated := false
}
),"Std.HashMap", "app (GetElem.getElem) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
rowState := #["Std.DHashMap", "Std.DHashMap.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.get,
renderedStatement := "Std.DHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (h : a ∈ m) : β a",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.Const.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.Const.get,
renderedStatement := "Std.DHashMap.Raw.Const.get.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (m : Std.DHashMap.Raw α fun x => β) (a : α) (h : a ∈ m) : β",
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.get,
renderedStatement := "Std.ExtDHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [LawfulBEq α] (m : Std.ExtDHashMap α β) (a : α) (h : a ∈ m) : β a",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.get,
renderedStatement := "Std.DTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap α β cmp) (a : α) (h : a ∈ t) : β a",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.get,
renderedStatement := "Std.DTreeMap.Raw.get.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap.Raw α β cmp) (a : α) (h : a ∈ t) : β a",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.get,
renderedStatement := "Std.ExtDTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (h : a ∈ t) : β a",
isDeprecated := false }),"Std.HashMap", "app (GetElem.getElem) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.HashMap*)", displayShort := "Std.HashMap[·]" },"Std.HashMap.Raw", "app (GetElem.getElem) (Std.HashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.HashMap.Raw*)", displayShort := "Std.HashMap.Raw[·]" },"Std.ExtHashMap", "app (GetElem.getElem) (Std.ExtHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.ExtHashMap*)", displayShort := "Std.ExtHashMap[·]" },"Std.TreeMap", "app (GetElem.getElem) (Std.TreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.TreeMap*)", displayShort := "Std.TreeMap[·]" },"Std.TreeMap.Raw", "app (GetElem.getElem) (Std.TreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.TreeMap.Raw*)", displayShort := "Std.TreeMap.Raw[·]" },"Std.ExtTreeMap", "app (GetElem.getElem) (Std.ExtTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.ExtTreeMap*)", displayShort := "Std.ExtTreeMap[·]" },"Std.HashSet", "Std.HashSet.get", .declaration (Declaration.def {
name := `Std.HashSet.get
renderedStatement := "Std.HashSet.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a : α) (h : a ∈ m) : α"
isDeprecated := false
}
),"Std.HashSet.Raw", "Std.HashSet.Raw.get", .declaration (Declaration.def {
name := `Std.HashSet.Raw.get
renderedStatement := "Std.HashSet.Raw.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α) (a : α) (h : a ∈ m) : α"
isDeprecated := false
}
),"Std.ExtHashSet", "Std.ExtHashSet.get", .declaration (Declaration.def {
name := `Std.ExtHashSet.get
renderedStatement := "Std.ExtHashSet.get.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a : α) (h : a ∈ m) : α"
isDeprecated := false
}
),"Std.TreeSet", "Std.TreeSet.get", .declaration (Declaration.def {
name := `Std.TreeSet.get
renderedStatement := "Std.TreeSet.get.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) (a : α) (h : a ∈ t) : α"
isDeprecated := false
}
),"Std.TreeSet.Raw", "Std.TreeSet.Raw.get", .declaration (Declaration.def {
name := `Std.TreeSet.Raw.get
renderedStatement := "Std.TreeSet.Raw.get.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp) (a : α) (h : a ∈ t) : α"
isDeprecated := false
}
),"Std.ExtTreeSet", "Std.ExtTreeSet.get", .declaration (Declaration.def {
name := `Std.ExtTreeSet.get
renderedStatement := "Std.ExtTreeSet.get.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp) (a : α)\n (h : a ∈ t) : α"
isDeprecated := false
}
),]
{ key := "app (GetElem.getElem) (Std.ExtTreeMap*)", displayShort := "Std.ExtTreeMap[·]" },"Std.HashSet", "Std.HashSet.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.get,
renderedStatement := "Std.HashSet.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a : α) (h : a ∈ m) : α",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.get,
renderedStatement := "Std.HashSet.Raw.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α) (a : α)\n (h : a ∈ m) : α",
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.get,
renderedStatement := "Std.ExtHashSet.get.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a : α) (h : a ∈ m) : α",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.get,
renderedStatement := "Std.TreeSet.get.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) (a : α)\n (h : a ∈ t) : α",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.get,
renderedStatement := "Std.TreeSet.Raw.get.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp) (a : α)\n (h : a ∈ t) : α",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.get,
renderedStatement := "Std.ExtTreeSet.get.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (a : α) (h : a ∈ t) : α",
isDeprecated := false }),]
metadata := {
status := .bad
comment := "Should *Set have GetElem?"

View File

@@ -20,23 +20,75 @@ def sequentialContainers : Node :=
namespace AssociativeContainers
def associativeQueryOperations : AssociationTable .subexpression
[`Std.DHashMap, `Std.DHashMap.Raw, `Std.ExtDHashMap, `Std.DTreeMap, `Std.DTreeMap.Raw, `Std.ExtDTreeMap, `Std.HashMap,
`Std.HashMap.Raw, `Std.ExtHashMap, `Std.TreeMap, `Std.TreeMap.Raw, `Std.ExtTreeMap, `Std.HashSet, `Std.HashSet.Raw, `Std.ExtHashSet,
`Std.TreeSet, `Std.TreeSet.Raw, `Std.ExtTreeSet] where
def associativeContainers : List Lean.Name :=
[`Std.DHashMap, `Std.DHashMap.Raw, `Std.ExtDHashMap, `Std.DTreeMap, `Std.DTreeMap.Raw, `Std.ExtDTreeMap, `Std.HashMap,
`Std.HashMap.Raw, `Std.ExtHashMap, `Std.TreeMap, `Std.TreeMap.Raw, `Std.ExtTreeMap, `Std.HashSet, `Std.HashSet.Raw, `Std.ExtHashSet,
`Std.TreeSet, `Std.TreeSet.Raw, `Std.ExtTreeSet]
def associativeQueryOperations : AssociationTable .subexpression associativeContainers where
id := "associative-query-operations"
title := "Associative query operations"
description := "Operations that take as input an associative container and return a 'single' piece of information (e.g., `GetElem` or `isEmpty`, but not `toList`)."
dataSources n :=
(DataSource.declarationsInNamespace n .definitionsOnly)
(DataSource.definitionsInNamespace n)
|>.map Subexpression.declaration
|>.or (DataSource.getElem n)
def associativeCreationOperations : AssociationTable .subexpression associativeContainers where
id := "associative-creation-operations"
title := "Associative creation operations"
description := "Operations that create a new associative container"
dataSources n :=
(DataSource.definitionsInNamespace n)
|>.map Subexpression.declaration
|>.or (DataSource.emptyCollection n)
def associativeModificationOperations : AssociationTable .subexpression associativeContainers where
id := "associative-modification-operations"
title := "Associative modification operations"
description := "Operations that both accept and return an associative container"
dataSources n :=
(DataSource.definitionsInNamespace n)
|>.map Subexpression.declaration
def associativeCreateThenQuery : Table .subexpression .subexpression .declaration associativeContainers where
id := "associative-create-then-query"
title := "Associative create then query"
description := "Lemmas that say what happens when creating a new associative container and then immediately querying from it"
rowsFrom := .table associativeCreationOperations
columnsFrom := .table associativeQueryOperations
cellData := .classic _ { relevantNamespaces := associativeContainers }
def allOperationsCovered : Assertion where
widgetId := "associative-all-operations-covered"
title := "All operations on associative containers covered"
description := "All operations on an associative container should appear in at least one of the tables"
check := do
let allValuesArray : Array String #[associativeQueryOperations, associativeCreationOperations, associativeModificationOperations].flatMapM valuesInAssociationTable
let allValues : Std.HashSet String := Std.HashSet.ofArray allValuesArray
let env Lean.getEnv
let mut numBad := 0
for (n, _) in env.constants do
if associativeContainers.any (fun namesp => namesp.isPrefixOf n) then
if !n.toString allValues then
numBad := numBad + 1
return #[{
assertionId := "all-covered"
description := "All operations should be covered"
passed := numBad == 0
message := if numBad = 0 then "All operations were covered" else s!"There were {numBad} operations that were not covered."
}]
end AssociativeContainers
open AssociativeContainers in
def associativeContainers : Node :=
.section "associative-containers" "Associative containers" #[
.associationTable AssociativeContainers.associativeQueryOperations
.associationTable associativeQueryOperations,
.associationTable associativeCreationOperations,
.associationTable associativeModificationOperations,
.table associativeCreateThenQuery,
.assertion allOperationsCovered
]
namespace PersistentDataStructures

View File

@@ -3,8 +3,10 @@
lake exe grove-stdlib --full metadata.json
cd .lake/packages/grove/frontend
npm install
cp ../../../../metadata.json public/metadata.json
if [ -f "../../../../invalidated.json" ]; then
GROVE_DATA_LOCATION=../../../../metadata.json GROVE_UPSTREAM_INVALIDATED_FACTS_LOCATION=../../../../invalidated.json npm run dev
cp ../../../../invalidated.json public/invalidated.json
GROVE_DATA_LOCATION=public/metadata.json GROVE_UPSTREAM_INVALIDATED_FACTS_LOCATION=public/invalidated.json npm run dev
else
GROVE_DATA_LOCATION=../../../../metadata.json npm run dev
fi
GROVE_DATA_LOCATION=public/metadata.json npm run dev
fi

View File

@@ -5,7 +5,7 @@
"type": "git",
"subDir": "backend",
"scope": "",
"rev": "e8127fc6554b99fb988ecdceb770a5e112afbe24",
"rev": "3e8aabdea58c11813c5d3b7eeb187ded44ee9a34",
"name": "grove",
"manifestFile": "lake-manifest.json",
"inputRev": "master",

View File

@@ -1,9 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
cmake --preset release -DUSE_LAKE=ON 1>&2
# We benchmark against stage 2 to test new optimizations.
timeout -s KILL 1h time bash -c 'mkdir -p build/release; cd build/release; cmake ../.. && make -j$(nproc) stage2' 1>&2
timeout -s KILL 1h time make -C build/release -j$(nproc) stage2 1>&2
export PATH=$PWD/build/release/stage2/bin:$PATH
# The extra opts used to be passed to the Makefile during benchmarking only but with Lake it is
# easier to configure them statically.
cmake -B build/release/stage2 -S src -DLEAN_EXTRA_LAKEFILE_TOML='weakLeanArgs=["-Dprofiler=true", "-Dprofiler.threshold=9999999", "--stats"]' 1>&2
cd tests/bench
timeout -s KILL 1h time temci exec --config speedcenter.yaml --in speedcenter.exec.velcom.yaml 1>&2
temci report run_output.yaml --reporter codespeed2

View File

@@ -195,7 +195,7 @@ def execute_release_steps(repo, version, config):
run_command(f"git checkout {default_branch} && git pull", cwd=repo_path)
# Special rc1 safety check for batteries and mathlib4 (before creating any branches)
if re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"] and version.endswith('-rc1'):
if repo_name in ["batteries", "mathlib4"] and version.endswith('-rc1'):
print(blue("This repo has nightly-testing infrastructure"))
print(blue(f"Checking if nightly-testing can be safely merged into bump/{version.split('-rc')[0]}..."))
@@ -403,7 +403,7 @@ def execute_release_steps(repo, version, config):
raise
# Handle special merging cases
if re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"]:
if version.endswith('-rc1') and repo_name in ["batteries", "mathlib4"]:
print(blue("This repo uses `bump/v4.X.0` branches for reviewed content from nightly-testing."))
# Determine which remote to use for bump branches
@@ -474,7 +474,7 @@ def execute_release_steps(repo, version, config):
print(green("✅ Merge completed successfully with automatic conflict resolution"))
elif re.search(r'rc\d+$', version):
elif version.endswith('-rc1'):
# For all other repos with rc versions, merge nightly-testing
if repo_name in ["verso", "reference-manual"]:
print(yellow("This repo does development on nightly-testing: remember to rebase merge the PR."))

View File

@@ -533,12 +533,21 @@ else()
OUTPUT_VARIABLE GIT_SHA1
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "stage0 sha1: ${GIT_SHA1}")
# Now that we've prepared the information for the next stage, we can forget that we will use
# Lake in the future as we won't use it in this stage
set(USE_LAKE OFF)
else()
set(GIT_SHA1 "")
endif()
endif()
configure_file("${LEAN_SOURCE_DIR}/githash.h.in" "${LEAN_BINARY_DIR}/githash.h")
if(USE_LAKE AND ${STAGE} EQUAL 0)
# Now that we've prepared the information for the next stage, we can forget that we will use
# Lake in the future as we won't use it in this stage
set(USE_LAKE OFF)
endif()
# Windows uses ";" as a path separator. We use `LEAN_PATH_SEPARATOR` on scripts such as lean.mk.in
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(LEAN_PATH_SEPARATOR ";")
@@ -634,8 +643,6 @@ else()
set(LEAN_OBJS ${LEAN_OBJS} $<TARGET_OBJECTS:library>)
add_subdirectory(library/constructions)
set(LEAN_OBJS ${LEAN_OBJS} $<TARGET_OBJECTS:constructions>)
add_subdirectory(library/compiler)
set(LEAN_OBJS ${LEAN_OBJS} $<TARGET_OBJECTS:compiler>)
# leancpp without `initialize` (see `leaninitialize` above)
add_library(leancpp_1 STATIC ${LEAN_OBJS})
@@ -814,6 +821,12 @@ if(LEAN_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "${LEAN_INSTALL_PREFIX}/lean-${LEAN_VERSION_STRING}${LEAN_INSTALL_SUFFIX}")
endif()
if (STAGE GREATER 1)
# The build of stage2+ may depend on local changes made to src/ that are not reflected by the
# commit hash in stage1/bin/lean, so we make sure to disable the global cache
string(APPEND LEAN_EXTRA_LAKEFILE_TOML "\n\nenableArtifactCache = false")
endif()
# Escape for `make`. Yes, twice.
string(REPLACE "$" "\\\$$" CMAKE_EXE_LINKER_FLAGS_MAKE "${CMAKE_EXE_LINKER_FLAGS}")
configure_file(${LEAN_SOURCE_DIR}/stdlib.make.in ${CMAKE_BINARY_DIR}/stdlib.make)
@@ -840,6 +853,10 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(LAKE_LIB_PREFIX "lib")
endif()
if(USE_LAKE AND STAGE EQUAL 1)
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/lakefile.toml)
if(USE_LAKE)
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${CMAKE_BINARY_DIR}/lakefile.toml)
# copy for editing
if(STAGE EQUAL 1)
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/lakefile.toml)
endif()
endif()

View File

@@ -39,7 +39,7 @@ This gadget is supported by
* `simp`, `dsimp` and `rw` in the right-hand-side of an equation
* `simp` in the assumptions of congruence rules
It is ineffective in other positions (hyptheses of rewrite rules) or when used by other tactics
It is ineffective in other positions (hypotheses of rewrite rules) or when used by other tactics
(e.g. `apply`).
-/
@[simp , expose]

View File

@@ -12,7 +12,7 @@ public import Init.Control.Basic
public import Init.Control.Id
public import Init.Coe
public section
@[expose] public section
namespace Except
variable {ε : Type u}

View File

@@ -52,4 +52,4 @@ instance ReaderT.tryFinally [MonadFinally m] : MonadFinally (ReaderT ρ m) where
A monad with access to a read-only value of type `ρ`. The value can be locally overridden by
`withReader`, but it cannot be mutated.
-/
@[reducible] def ReaderM (ρ : Type u) := ReaderT ρ Id
abbrev ReaderM (ρ : Type u) := ReaderT ρ Id

View File

@@ -262,7 +262,7 @@ resulting in `t'`, which becomes the new target subgoal. -/
syntax (name := convConvSeq) "conv" " => " convSeq : conv
/-- `· conv` focuses on the main conv goal and tries to solve it using `s`. -/
macro dot:patternIgnore("·" <|> ".") s:convSeq : conv => `(conv| {%$dot ($s) })
macro dot:patternIgnore("· " <|> ". ") s:convSeq : conv => `(conv| {%$dot ($s) })
/-- `fail_if_success t` fails if the tactic `t` succeeds. -/
@@ -342,7 +342,7 @@ This is the conv mode version of the `lift_lets` tactic.
syntax (name := liftLets) "lift_lets " optConfig : conv
/--
Transforms `let` expressions into `have` expressions within th etarget expression when possible.
Transforms `let` expressions into `have` expressions within the target expression when possible.
This is the conv mode version of the `let_to_have` tactic.
-/
syntax (name := letToHave) "let_to_have" : conv

View File

@@ -752,6 +752,8 @@ Unlike `x ≠ y` (which is notation for `Ne x y`), this is `Bool` valued instead
@[inherit_doc] infix:50 " != " => bne
macro_rules | `($x != $y) => `(binrel_no_prop% bne $x $y)
recommended_spelling "bne" for "!=" in [bne, «term_!=_»]
/-- `ReflBEq α` says that the `BEq` implementation is reflexive. -/
@@ -853,6 +855,8 @@ and asserts that `a` and `b` are not equal.
@[inherit_doc] infix:50 "" => Ne
macro_rules | `($x $y) => `(binrel% Ne $x $y)
recommended_spelling "ne" for "" in [Ne, «term__»]
section Ne

View File

@@ -10,7 +10,7 @@ prelude
public import Init.Classical
public import Init.ByCases
public section
@[expose] public section
namespace Lean.Data.AC
inductive Expr

View File

@@ -180,7 +180,7 @@ in-place when the reference to the array is unique.
This avoids overhead due to unboxing a `Nat` used as an index.
-/
@[extern "lean_array_uset"]
@[extern "lean_array_uset", expose]
def uset (xs : Array α) (i : USize) (v : α) (h : i.toNat < xs.size) : Array α :=
xs.set i.toNat v h
@@ -1024,7 +1024,7 @@ The optional parameters `start` and `stop` control the region of the array to wh
applied. Iteration proceeds from `start` (inclusive) to `stop` (exclusive), so `f` is not invoked
unless `start < stop`. By default, the entire array is used.
-/
@[inline]
@[inline, expose]
protected def forM {α : Type u} {m : Type v Type w} [Monad m] (f : α m PUnit) (as : Array α) (start := 0) (stop := as.size) : m PUnit :=
as.foldlM (fun _ => f) start stop

View File

@@ -382,11 +382,12 @@ theorem eraseIdx_ne_empty_iff {xs : Array α} {i : Nat} {h} : xs.eraseIdx i ≠
simp [h]
· simp
@[grind ]
theorem mem_of_mem_eraseIdx {xs : Array α} {i : Nat} {h} {a : α} (h : a xs.eraseIdx i) : a xs := by
rcases xs with xs
simpa using List.mem_of_mem_eraseIdx (by simpa using h)
grind_pattern mem_of_mem_eraseIdx => a xs.eraseIdx i
theorem eraseIdx_append_of_lt_size {xs : Array α} {k : Nat} (hk : k < xs.size) (ys : Array α) (h) :
eraseIdx (xs ++ ys) k = eraseIdx xs k ++ ys := by
rcases xs with l

View File

@@ -387,7 +387,7 @@ theorem find?_eq_some_iff_getElem {xs : Array α} {p : α → Bool} {b : α} :
/-! ### findIdx -/
@[grind =]
theorem findIdx_empty : findIdx p #[] = 0 := rfl
theorem findIdx_empty : findIdx p #[] = 0 := by simp
@[grind =]
theorem findIdx_singleton {a : α} {p : α Bool} :

View File

@@ -129,7 +129,7 @@ theorem none_eq_getElem?_iff {xs : Array α} {i : Nat} : none = xs[i]? ↔ xs.si
theorem getElem?_eq_none {xs : Array α} (h : xs.size i) : xs[i]? = none := by
simp [h]
grind_pattern Array.getElem?_eq_none => xs.size i, xs[i]?
grind_pattern Array.getElem?_eq_none => xs.size, xs[i]?
@[simp] theorem getElem?_eq_getElem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i]? = some xs[i] :=
getElem?_pos ..
@@ -872,24 +872,24 @@ theorem elem_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
@[grind] theorem all_empty [BEq α] {p : α Bool} : (#[] : Array α).all p = true := by simp
/-- Variant of `any_push` with a side condition on `stop`. -/
@[simp, grind] theorem any_push' [BEq α] {xs : Array α} {a : α} {p : α Bool} (h : stop = xs.size + 1) :
@[simp, grind] theorem any_push' {xs : Array α} {a : α} {p : α Bool} (h : stop = xs.size + 1) :
(xs.push a).any p 0 stop = (xs.any p || p a) := by
cases xs
rw [List.push_toArray]
simp [h]
theorem any_push [BEq α] {xs : Array α} {a : α} {p : α Bool} :
theorem any_push {xs : Array α} {a : α} {p : α Bool} :
(xs.push a).any p = (xs.any p || p a) :=
any_push' (by simp)
/-- Variant of `all_push` with a side condition on `stop`. -/
@[simp, grind] theorem all_push' [BEq α] {xs : Array α} {a : α} {p : α Bool} (h : stop = xs.size + 1) :
@[simp, grind] theorem all_push' {xs : Array α} {a : α} {p : α Bool} (h : stop = xs.size + 1) :
(xs.push a).all p 0 stop = (xs.all p && p a) := by
cases xs
rw [List.push_toArray]
simp [h]
theorem all_push [BEq α] {xs : Array α} {a : α} {p : α Bool} :
theorem all_push {xs : Array α} {a : α} {p : α Bool} :
(xs.push a).all p = (xs.all p && p a) :=
all_push' (by simp)
@@ -985,12 +985,13 @@ theorem mem_set {xs : Array α} {i : Nat} (h : i < xs.size) {a : α} :
simp [mem_iff_getElem]
exact i, (by simpa using h), by simp
@[grind ]
theorem mem_or_eq_of_mem_set
{xs : Array α} {i : Nat} {a b : α} {w : i < xs.size} (h : a xs.set i b) : a xs a = b := by
cases xs
simpa using List.mem_or_eq_of_mem_set (by simpa using h)
grind_pattern mem_or_eq_of_mem_set => a xs.set i b
/-! ### setIfInBounds -/
@[simp, grind] theorem setIfInBounds_empty {i : Nat} {a : α} :
@@ -1675,12 +1676,12 @@ theorem filterMap_eq_map' {f : α → β} (w : stop = as.size) :
filterMap (fun x => some (f x)) as 0 stop = map f as :=
filterMap_eq_map w
@[simp] theorem filterMap_some_fun : filterMap (some : α Option α) = id := by
theorem filterMap_some_fun : filterMap (some : α Option α) = id := by
funext xs
cases xs
simp
@[grind] theorem filterMap_some {xs : Array α} : filterMap some xs = xs := by
@[simp, grind] theorem filterMap_some {xs : Array α} : filterMap some xs = xs := by
cases xs
simp

View File

@@ -6,9 +6,12 @@ Author: Kim Morrison
module
prelude
public import Init.Data.Array.Basic
public import Init.Data.Nat.Lemmas
public import Init.Data.Range
public import Init.Core
import Init.Data.Array.Basic
import Init.Data.Nat.Lemmas
import Init.Data.Range.Polymorphic.Iterators
import Init.Data.Range.Polymorphic.Nat
import Init.Data.Iterators.Consumers
public section
@@ -26,9 +29,9 @@ Specifically, `Array.lex as bs lt` is true if
* there is an index `i` such that `lt as[i] bs[i]`, and for all `j < i`, `as[j] == bs[j]`.
-/
def lex [BEq α] (as bs : Array α) (lt : α α Bool := by exact (· < ·)) : Bool := Id.run do
for h : i in [0 : min as.size bs.size] do
-- TODO: `omega` should be able to find this itself.
have : i < min as.size bs.size := Membership.get_elem_helper h rfl
for h : i in 0...(min as.size bs.size) do
-- TODO: `get_elem_tactic` should be able to find this itself.
have : i < min as.size bs.size := Std.PRange.lt_upper_of_mem h
if lt as[i] bs[i] then
return true
else if as[i] != bs[i] then

View File

@@ -6,9 +6,12 @@ Author: Kim Morrison
module
prelude
public import all Init.Data.Array.Lex.Basic
import all Init.Data.Array.Lex.Basic
public import Init.Data.Array.Lex.Basic
public import Init.Data.Array.Lemmas
public import Init.Data.List.Lex
import Init.Data.Range.Polymorphic.Lemmas
import Init.Data.Range.Polymorphic.NatLemmas
public section
@@ -19,28 +22,55 @@ namespace Array
/-! ### Lexicographic ordering -/
@[simp, grind =] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray l₁ < l₂ := Iff.rfl
@[simp, grind =] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray l₂.toArray l₁ l₂ := Iff.rfl
@[simp] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray l₁ < l₂ := Iff.rfl
@[simp] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray l₂.toArray l₁ l₂ := Iff.rfl
@[simp, grind =] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp, grind =] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ys.toList xs ys := Iff.rfl
@[simp] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ys.toList xs ys := Iff.rfl
grind_pattern _root_.List.lt_toArray => l₁.toArray < l₂.toArray
grind_pattern _root_.List.le_toArray => l₁.toArray l₂.toArray
grind_pattern lt_toList => xs.toList < ys.toList
grind_pattern le_toList => xs.toList ys.toList
protected theorem not_lt_iff_ge [LT α] {xs ys : Array α} : ¬ xs < ys ys xs := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Array α} :
protected theorem not_le_iff_gt [LT α] {xs ys : Array α} :
¬ xs ys ys < xs :=
Decidable.not_not
Classical.not_not
@[simp] theorem lex_empty [BEq α] {lt : α α Bool} {xs : Array α} : xs.lex #[] lt = false := by
simp [lex]
rw [lex, Std.PRange.forIn'_eq_match]
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
private theorem cons_lex_cons.forIn'_congr_aux [Monad m] {as bs : ρ} {_ : Membership α ρ}
[ForIn' m ρ α inferInstance] (w : as = bs)
{b b' : β} (hb : b = b')
{f : (a' : α) a' as β m (ForInStep β)}
{g : (a' : α) a' bs β m (ForInStep β)}
(h : a m b, f a (by simpa [w] using m) b = g a m b) :
forIn' as b f = forIn' bs b' g := by
cases hb
cases w
have : f = g := by
ext a ha acc
apply h
cases this
rfl
private theorem cons_lex_cons [BEq α] {lt : α α Bool} {a b : α} {xs ys : Array α} :
(#[a] ++ xs).lex (#[b] ++ ys) lt =
(lt a b || a == b && xs.lex ys lt) := by
simp only [lex]
simp only [Std.Range.forIn'_eq_forIn'_range', size_append, List.size_toArray, List.length_singleton,
Nat.add_comm 1]
simp [Nat.add_min_add_right, List.range'_succ, getElem_append_left, List.range'_succ_left,
getElem_append_right]
simp only [lex, size_append, List.size_toArray, List.length_cons, List.length_nil, Nat.zero_add,
Nat.add_min_add_left, Nat.add_lt_add_iff_left, Std.PRange.forIn'_eq_forIn'_toList]
conv =>
lhs; congr; congr
rw [cons_lex_cons.forIn'_congr_aux Std.PRange.toList_eq_match rfl (fun _ _ _ => rfl)]
simp only [Std.PRange.SupportsUpperBound.IsSatisfied, bind_pure_comp, map_pure]
rw [cons_lex_cons.forIn'_congr_aux (if_pos (by omega)) rfl (fun _ _ _ => rfl)]
simp only [Std.PRange.toList_open_eq_toList_closed_of_isSome_succ? (lo := 0) (h := rfl),
Std.PRange.UpwardEnumerable.succ?, Nat.add_comm 1, Std.PRange.Nat.ClosedOpen.toList_succ_succ,
Option.get_some, List.forIn'_cons, List.size_toArray, List.length_cons, List.length_nil,
Nat.lt_add_one, getElem_append_left, List.getElem_toArray, List.getElem_cons_zero]
cases lt a b
· rw [bne]
cases a == b <;> simp
@@ -49,10 +79,17 @@ private theorem cons_lex_cons [BEq α] {lt : αα → Bool} {a b : α} {xs
@[simp, grind =] theorem _root_.List.lex_toArray [BEq α] {lt : α α Bool} {l₁ l₂ : List α} :
l₁.toArray.lex l₂.toArray lt = l₁.lex l₂ lt := by
induction l₁ generalizing l₂ with
| nil => cases l₂ <;> simp [lex]
| nil =>
cases l₂
· rw [lex, Std.PRange.forIn'_eq_match]
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
· rw [lex, Std.PRange.forIn'_eq_match]
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
| cons x l₁ ih =>
cases l₂ with
| nil => simp [lex]
| nil =>
rw [lex, Std.PRange.forIn'_eq_match]
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
| cons y l₂ =>
rw [List.toArray_cons, List.toArray_cons y, cons_lex_cons, List.lex, ih]
@@ -94,7 +131,7 @@ instance [LT α] [Trans (· < · : αα → Prop) (· < ·) (· < ·)] :
Trans (· < · : Array α Array α Prop) (· < ·) (· < ·) where
trans h₁ h₂ := Array.lt_trans h₁ h₂
protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem lt_of_le_of_lt [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -102,7 +139,7 @@ protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
{xs ys zs : Array α} (h₁ : xs ys) (h₂ : ys < zs) : xs < zs :=
List.lt_of_le_of_lt h₁ h₂
protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_trans [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -110,7 +147,7 @@ protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
{xs ys zs : Array α} (h₁ : xs ys) (h₂ : ys zs) : xs zs :=
fun h₃ => h₁ (Array.lt_of_le_of_lt h₂ h₃)
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -122,34 +159,34 @@ protected theorem lt_asymm [LT α]
[i : Std.Asymm (· < · : α α Prop)]
{xs ys : Array α} (h : xs < ys) : ¬ ys < xs := List.lt_asymm h
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Asymm (· < · : α α Prop)] :
Std.Asymm (· < · : Array α Array α Prop) where
asymm _ _ := Array.lt_asymm
protected theorem le_total [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_total [LT α]
[i : Std.Total (¬ · < · : α α Prop)] (xs ys : Array α) : xs ys ys xs :=
List.le_total xs.toList ys.toList
@[simp] protected theorem not_lt [LT α]
{xs ys : Array α} : ¬ xs < ys ys xs := Iff.rfl
@[simp] protected theorem not_le [DecidableEq α] [LT α] [DecidableLT α]
{xs ys : Array α} : ¬ ys xs xs < ys := Decidable.not_not
@[simp] protected theorem not_le [LT α]
{xs ys : Array α} : ¬ ys xs xs < ys := Classical.not_not
protected theorem le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_of_lt [LT α]
[i : Std.Total (¬ · < · : α α Prop)]
{xs ys : Array α} (h : xs < ys) : xs ys :=
List.le_of_lt h
protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_lt_or_eq [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
[Std.Total (¬ · < · : α α Prop)]
{xs ys : Array α} : xs ys xs < ys xs = ys := by
simpa using List.le_iff_lt_or_eq (l₁ := xs.toList) (l₂ := ys.toList)
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Total (¬ · < · : α α Prop)] :
Std.Total (· · : Array α Array α Prop) where
total := Array.le_total
@@ -218,7 +255,7 @@ theorem lex_eq_false_iff_exists [BEq α] [PartialEquivBEq α] (lt : αα
cases l₂
simp_all [List.lex_eq_false_iff_exists]
protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Array α} :
protected theorem lt_iff_exists [LT α] {xs ys : Array α} :
xs < ys
(xs = ys.take xs.size xs.size < ys.size)
( (i : Nat) (h₁ : i < xs.size) (h₂ : i < ys.size),
@@ -228,7 +265,7 @@ protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {xs ys
cases ys
simp [List.lt_iff_exists]
protected theorem le_iff_exists [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_exists [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)] {xs ys : Array α} :
@@ -248,7 +285,7 @@ theorem append_left_lt [LT α] {xs ys zs : Array α} (h : ys < zs) :
cases zs
simpa using List.append_left_lt h
theorem append_left_le [DecidableEq α] [LT α] [DecidableLT α]
theorem append_left_le [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -272,7 +309,7 @@ protected theorem map_lt [LT α] [LT β]
cases ys
simpa using List.map_lt w h
protected theorem map_le [DecidableEq α] [LT α] [DecidableLT α] [DecidableEq β] [LT β] [DecidableLT β]
protected theorem map_le [LT α] [LT β]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]

View File

@@ -6,7 +6,8 @@ Authors: Leonardo de Moura
module
prelude
public import Init.Data.Array.Basic
public import Init.GetElem
import Init.Data.Array.GetLit
public import Init.Data.Slice.Basic
public section
@@ -159,64 +160,10 @@ instance : EmptyCollection (Subarray α) :=
instance : Inhabited (Subarray α) :=
{}
/--
The run-time implementation of `ForIn.forIn` for `Subarray`, which allows it to be used with `for`
loops in `do`-notation.
This definition replaces `Subarray.forIn`.
/-!
`ForIn`, `foldlM`, `foldl` and other operations are implemented in `Init.Data.Slice.Array.Iterator`
using the slice iterator.
-/
@[inline] unsafe def forInUnsafe {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (s : Subarray α) (b : β) (f : α β m (ForInStep β)) : m β :=
let sz := USize.ofNat s.stop
let rec @[specialize] loop (i : USize) (b : β) : m β := do
if i < sz then
let a := s.array.uget i lcProof
match ( f a b) with
| ForInStep.done b => pure b
| ForInStep.yield b => loop (i+1) b
else
pure b
loop (USize.ofNat s.start) b
/--
The implementation of `ForIn.forIn` for `Subarray`, which allows it to be used with `for` loops in
`do`-notation.
-/
-- TODO: provide reference implementation
@[implemented_by Subarray.forInUnsafe]
protected opaque forIn {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (s : Subarray α) (b : β) (f : α β m (ForInStep β)) : m β :=
pure b
instance : ForIn m (Subarray α) α where
forIn := Subarray.forIn
/--
Folds a monadic operation from left to right over the elements in a subarray.
An accumulator of type `β` is constructed by starting with `init` and monadically combining each
element of the subarray with the current accumulator value in turn. The monad in question may permit
early termination or repetition.
Examples:
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := "") fun acc x => do
let l ← Option.guard (· ≠ 0) x.length
return s!"{acc}({l}){x} "
```
```output
some "(3)red (5)green (4)blue "
```
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := 0) fun acc x => do
let l ← Option.guard (· ≠ 5) x.length
return s!"{acc}({l}){x} "
```
```output
none
```
-/
@[inline]
def foldlM {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (f : β α m β) (init : β) (as : Subarray α) : m β :=
as.array.foldlM f (init := init) (start := as.start) (stop := as.stop)
/--
Folds a monadic operation from right to left over the elements in a subarray.
@@ -313,20 +260,6 @@ The elements are processed starting at the highest index and moving down.
def forRevM {α : Type u} {m : Type v Type w} [Monad m] (f : α m PUnit) (as : Subarray α) : m PUnit :=
as.array.forRevM f (start := as.stop) (stop := as.start)
/--
Folds an operation from left to right over the elements in a subarray.
An accumulator of type `β` is constructed by starting with `init` and combining each
element of the subarray with the current accumulator value in turn.
Examples:
* `#["red", "green", "blue"].toSubarray.foldl (· + ·.length) 0 = 12`
* `#["red", "green", "blue"].toSubarray.popFront.foldl (· + ·.length) 0 = 9`
-/
@[inline]
def foldl {α : Type u} {β : Type v} (f : β α β) (init : β) (as : Subarray α) : β :=
Id.run <| as.foldlM (pure <| f · ·) (init := init)
/--
Folds an operation from right to left over the elements in a subarray.
@@ -334,8 +267,8 @@ An accumulator of type `β` is constructed by starting with `init` and combining
subarray with the current accumulator value in turn, moving from the end to the start.
Examples:
* `#eval #["red", "green", "blue"].toSubarray.foldr (·.length + ·) 0 = 12`
* `#["red", "green", "blue"].toSubarray.popFront.foldlr (·.length + ·) 0 = 9`
* `#["red", "green", "blue"].toSubarray.foldr (·.length + ·) 0 = 12`
* `#["red", "green", "blue"].toSubarray.popFront.foldr (·.length + ·) 0 = 9`
-/
@[inline]
def foldr {α : Type u} {β : Type v} (f : α β β) (init : β) (as : Subarray α) : β :=
@@ -464,18 +397,6 @@ def toSubarray (as : Array α) (start : Nat := 0) (stop : Nat := as.size) : Suba
start_le_stop := Nat.le_refl _,
stop_le_array_size := Nat.le_refl _ }
/--
Allocates a new array that contains the contents of the subarray.
-/
@[coe]
def ofSubarray (s : Subarray α) : Array α := Id.run do
let mut as := mkEmpty (s.stop - s.start)
for a in s do
as := as.push a
return as
instance : Coe (Subarray α) (Array α) := ofSubarray
/-- A subarray with the provided bounds.-/
syntax:max term noWs "[" withoutPosition(term ":" term) "]" : term
/-- A subarray with the provided lower bound that extends to the rest of the array. -/
@@ -489,22 +410,3 @@ macro_rules
| `($a[$start : ]) => `(let a := $a; Array.toSubarray a $start a.size)
end Array
@[inherit_doc Array.ofSubarray]
def Subarray.toArray (s : Subarray α) : Array α :=
Array.ofSubarray s
instance : Append (Subarray α) where
append x y :=
let a := x.toArray ++ y.toArray
a.toSubarray 0 a.size
/-- `Subarray` representation. -/
protected def Subarray.repr [Repr α] (s : Subarray α) : Std.Format :=
repr s.toArray ++ ".toSubarray"
instance [Repr α] : Repr (Subarray α) where
reprPrec s _ := Subarray.repr s
instance [ToString α] : ToString (Subarray α) where
toString s := toString s.toArray

View File

@@ -12,7 +12,7 @@ public import Init.Data.Nat.Power2
public import Init.Data.Int.Bitwise
public import Init.Data.BitVec.BasicAux
public section
@[expose] public section
/-!
We define the basic algebraic structure of bitvectors. We choose the `Fin` representation over
@@ -35,7 +35,12 @@ protected def ofNatLt {n : Nat} (i : Nat) (p : i < 2 ^ n) : BitVec n :=
section Nat
instance natCastInst : NatCast (BitVec w) := BitVec.ofNat w
/--
`NatCast` instance for `BitVec`.
-/
-- As this is a lossy conversion, it should be removed as a global instance.
instance instNatCast : NatCast (BitVec w) where
natCast x := BitVec.ofNat w x
/-- Theorem for normalizing the bitvector literal representation. -/
-- TODO: This needs more usage data to assess which direction the simp should go.
@@ -731,10 +736,10 @@ def twoPow (w : Nat) (i : Nat) : BitVec w := 1#w <<< i
end bitwise
/-- The bitvector of width `w` that has the smallest value when interpreted as an integer. -/
def intMin (w : Nat) := twoPow w (w - 1)
@[expose] def intMin (w : Nat) := twoPow w (w - 1)
/-- The bitvector of width `w` that has the largest value when interpreted as an integer. -/
def intMax (w : Nat) := (twoPow w (w - 1)) - 1
@[expose] def intMax (w : Nat) := (twoPow w (w - 1)) - 1
/--
Computes a hash of a bitvector, combining 64-bit words using `mixHash`.

View File

@@ -15,7 +15,7 @@ public import Init.Data.BitVec.Decidable
public import Init.Data.BitVec.Lemmas
public import Init.Data.BitVec.Folds
public section
@[expose] public section
/-!
# Bit blasting of bitvectors
@@ -336,7 +336,7 @@ theorem add_eq_or_of_and_eq_zero {w : Nat} (x y : BitVec w)
(h : x &&& y = 0#w) : x + y = x ||| y := by
rw [add_eq_adc, adc, iunfoldr_replace (fun _ => false) (x ||| y)]
· rfl
· simp only [adcb, atLeastTwo, Bool.and_false, Bool.or_false, bne_false,
· simp only [adcb, atLeastTwo, Bool.and_false, Bool.or_false, bne_false,
Prod.mk.injEq, and_eq_false_imp]
intros i
replace h : (x &&& y).getLsbD i = (0#w).getLsbD i := by rw [h]
@@ -586,7 +586,6 @@ A recurrence that describes multiplication as repeated addition.
This function is useful for bit blasting multiplication.
-/
@[expose]
def mulRec (x y : BitVec w) (s : Nat) : BitVec w :=
let cur := if y.getLsbD s then (x <<< s) else 0
match s with
@@ -622,7 +621,7 @@ theorem setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow (x : BitVec w) (i
simp [hik', hik'']
omega
· ext k
simp only [and_twoPow,
simp only [and_twoPow,
]
by_cases hi : x.getLsbD i <;> simp [hi] <;> omega
@@ -1047,7 +1046,6 @@ theorem lawful_divSubtractShift (qr : DivModState w) (h : qr.Poised args) :
/-! ### Core division algorithm circuit -/
/-- A recursive definition of division for bit blasting, in terms of a shift-subtraction circuit. -/
@[expose]
def divRec {w : Nat} (m : Nat) (args : DivModArgs w) (qr : DivModState w) :
DivModState w :=
match m with
@@ -1944,7 +1942,7 @@ The remainder for `srem`, i.e. division with rounding to zero is negative
iff `x` is negative and `y` does not divide `x`.
We can eventually build fast circuits for the divisibility test `x.srem y = 0`.
-/
-/
theorem msb_srem {x y : BitVec w} : (x.srem y).msb =
(x.msb && decide (x.srem y 0)) := by
rw [msb_eq_toInt]

View File

@@ -745,7 +745,6 @@ theorem le_toNat_of_msb_true {w : Nat} {x : BitVec w} (h : x.msb = true) : 2 ^ (
`x.toInt` is less than `2^(w-1)`.
We phrase the fact in terms of `2^w` to prevent a case split on `w=0` when the lemma is used.
-/
@[grind]
theorem two_mul_toInt_lt {w : Nat} {x : BitVec w} : 2 * x.toInt < 2 ^ w := by
simp only [BitVec.toInt]
rcases w with _|w'
@@ -754,6 +753,8 @@ theorem two_mul_toInt_lt {w : Nat} {x : BitVec w} : 2 * x.toInt < 2 ^ w := by
simp only [Nat.zero_lt_succ, Nat.mul_lt_mul_left, Int.natCast_mul, Int.cast_ofNat_Int]
norm_cast; omega
grind_pattern two_mul_toInt_lt => x.toInt
theorem two_mul_toInt_le {w : Nat} {x : BitVec w} : 2 * x.toInt 2 ^ w - 1 :=
Int.le_sub_one_of_lt two_mul_toInt_lt
@@ -772,7 +773,6 @@ theorem toInt_le {w : Nat} {x : BitVec w} : x.toInt ≤ 2 ^ (w - 1) - 1 :=
`x.toInt` is greater than or equal to `-2^(w-1)`.
We phrase the fact in terms of `2^w` to prevent a case split on `w=0` when the lemma is used.
-/
@[grind]
theorem le_two_mul_toInt {w : Nat} {x : BitVec w} : -2 ^ w 2 * x.toInt := by
simp only [BitVec.toInt]
rcases w with _|w'
@@ -781,6 +781,8 @@ theorem le_two_mul_toInt {w : Nat} {x : BitVec w} : -2 ^ w ≤ 2 * x.toInt := by
simp only [Nat.zero_lt_succ, Nat.mul_lt_mul_left, Int.natCast_mul, Int.cast_ofNat_Int]
norm_cast; omega
grind_pattern le_two_mul_toInt => x.toInt
theorem le_toInt {w : Nat} (x : BitVec w) : -2 ^ (w - 1) x.toInt := by
by_cases h : w = 0
· subst h
@@ -3004,7 +3006,7 @@ which performs a case analysis on the start index, length, and the lengths of `x
· If the start index is entirely contained in the `xlo` bitvector, then grab the bits from `xlo`.
· If the start index is split between the two bitvectors,
then append `(w - start)` bits from `xlo` with `(len - (w - start))` bits from xhi.
Diagramatically:
Diagrammatically:
```
xhi xlo
(<---------------------](<-------w--------]
@@ -5136,7 +5138,7 @@ theorem setWidth_setWidth_succ_eq_setWidth_setWidth_of_getLsbD_false
/--
When the `(i+1)`th bit of `x` is true,
keeping the lower `(i + 1)` bits of `x` equalsk eeping the lower `i` bits
keeping the lower `(i + 1)` bits of `x` equals keeping the lower `i` bits
and then performing bitwise-or with `twoPow i = (1 << i)`,
-/
theorem setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true
@@ -5769,6 +5771,22 @@ theorem clzAuxRec_eq_clzAuxRec_of_le (x : BitVec w) (h : w - 1 ≤ n) :
simp [show w - 1 + (k + 1) = (w - 1 + k) + 1 by omega, clzAuxRec_succ, ihk,
show x.getLsbD (w - 1 + k + 1) = false by simp only [show w w - 1 + k + 1 by omega, getLsbD_of_ge]]
theorem clzAuxRec_eq_clzAuxRec_of_getLsbD_false {x : BitVec w} (h : i, n < i x.getLsbD i = false) :
x.clzAuxRec n = x.clzAuxRec (n + k) := by
induction k
· case zero => simp
· case succ k ihk =>
simp only [show n + (k + 1) = (n + k) + 1 by omega, clzAuxRec_succ]
by_cases hxn : x.getLsbD (n + k + 1)
· have : ¬ (i : Nat), n < i x.getLsbD i = false := by
simp only [Classical.not_forall, Bool.not_eq_false]
exists n + k + 1
simp [show n < n + k + 1 by omega, hxn]
contradiction
· simp only [hxn, Bool.false_eq_true, reduceIte]
exact ihk
/-! ### Inequalities (le / lt) -/
theorem ule_eq_not_ult (x y : BitVec w) : x.ule y = !y.ult x := by

View File

@@ -12,7 +12,7 @@ public import Init.Data.UInt.Basic
public import all Init.Data.UInt.BasicAux
public import Init.Data.Option.Basic
public section
@[expose] public section
universe u
structure ByteArray where
@@ -23,18 +23,10 @@ attribute [extern "lean_byte_array_data"] ByteArray.data
namespace ByteArray
deriving instance BEq for ByteArray
attribute [ext] ByteArray
/--
Checks whether two `ByteArray` instances have the same length and identical content. Normally used
via the `==` operator.
-/
@[extern "lean_byte_array_beq"]
protected def beq (a b : @& ByteArray) : Bool :=
BEq.beq a.data b.data
instance : BEq ByteArray := ByteArray.beq
instance : DecidableEq ByteArray :=
fun _ _ => decidable_of_decidable_of_iff ByteArray.ext_iff.symm

View File

@@ -8,7 +8,7 @@ module
prelude
public import Init.Data.UInt.BasicAux
public section
@[expose] public section
/-- Determines if the given integer is a valid [Unicode scalar value](https://www.unicode.org/glossary/#unicode_scalar_value).

View File

@@ -185,7 +185,9 @@ theorem foldrM_loop [Monad m] [LawfulMonad m] (f : Fin (n+1) → α → m α) (x
| zero =>
rw [foldrM_loop_zero, foldrM_loop_succ, pure_bind]
conv => rhs; rw [bind_pure (f 0 x)]
rfl
congr
funext
rw [foldrM_loop_zero]
| succ i ih =>
rw [foldrM_loop_succ, foldrM_loop_succ, bind_assoc]
congr; funext; exact ih ..

View File

@@ -927,24 +927,34 @@ For the induction:
-/
@[elab_as_elim] def reverseInduction {motive : Fin (n + 1) Sort _} (last : motive (Fin.last n))
(cast : i : Fin n, motive i.succ motive (castSucc i)) (i : Fin (n + 1)) : motive i :=
if hi : i = Fin.last n then _root_.cast (congrArg motive hi.symm) last
else
let j : Fin n := i, Nat.lt_of_le_of_ne (Nat.le_of_lt_succ i.2) fun h => hi (Fin.ext h)
cast _ (reverseInduction last cast j.succ)
termination_by n + 1 - i
decreasing_by decreasing_with
-- FIXME: we put the proof down here to avoid getting a dummy `have` in the definition
try simp only [Nat.succ_sub_succ_eq_sub]
exact Nat.add_sub_add_right .. Nat.sub_lt_sub_left i.2 (Nat.lt_succ_self i)
let rec go (j : Nat) (h) (h2 : i j) (x : motive j, h) : motive i :=
if hi : i.1 = j then _root_.cast (by simp [ hi]) x
else match j with
| 0 => by omega
| j + 1 => go j (by omega) (by omega) (cast j, by omega x)
go _ _ (by omega) last
@[simp] theorem reverseInduction_last {n : Nat} {motive : Fin (n + 1) Sort _} {zero succ} :
(reverseInduction zero succ (Fin.last n) : motive (Fin.last n)) = zero := by
rw [reverseInduction]; simp
rw [reverseInduction, reverseInduction.go]; simp
@[simp] theorem reverseInduction_castSucc_aux {n : Nat} {motive : Fin (n + 1) Sort _} {succ}
(i : Fin n) (j : Nat) (h) (h2 : i.1 < j) (zero : motive j, h) :
reverseInduction.go (motive := motive) succ i.castSucc j h (Nat.le_of_lt h2) zero =
succ i (reverseInduction.go succ i.succ j h h2 zero) := by
induction j generalizing i with
| zero => omega
| succ j ih =>
rw [reverseInduction.go, dif_neg (by exact Nat.ne_of_lt h2)]
by_cases hij : i = j
· subst hij; simp [reverseInduction.go]
dsimp only
rw [ih _ _ (by omega), eq_comm, reverseInduction.go, dif_neg (by change i.1 + 1 _; omega)]
@[simp] theorem reverseInduction_castSucc {n : Nat} {motive : Fin (n + 1) Sort _} {zero succ}
(i : Fin n) : reverseInduction (motive := motive) zero succ (castSucc i) =
succ i (reverseInduction zero succ i.succ) := by
rw [reverseInduction, dif_neg (Fin.ne_of_lt (Fin.castSucc_lt_last i))]; rfl
rw [reverseInduction, reverseInduction_castSucc_aux _ _ _ i.isLt, reverseInduction]
/--
Proves a statement by cases on the underlying `Nat` value in a `Fin (n + 1)`, checking whether the

View File

@@ -8,6 +8,7 @@ module
prelude
public import Init.Core
public import Init.Grind.Tactics
public section

View File

@@ -1737,32 +1737,6 @@ theorem emod_le (x y : Int) (n : Int) : emod_le_cert y n → x % y + n ≤ 0 :=
simp only [Int.add_comm, Int.sub_neg, Int.add_zero]
exact Int.emod_lt_of_pos x h
theorem natCast_nonneg (x : Nat) : (-1:Int) * NatCast.natCast x 0 := by
simp
theorem natCast_sub (x y : Nat)
: (NatCast.natCast (x - y) : Int)
=
if (NatCast.natCast y : Int) + (-1)*NatCast.natCast x 0 then
(NatCast.natCast x : Int) + -1*NatCast.natCast y
else
(0 : Int) := by
change ((x - y) : Int) = if (y : Int) + (-1)*x 0 then (x : Int) + (-1)*y else 0
rw [Int.neg_mul, Int.sub_eq_add_neg, Int.one_mul]
rw [Int.neg_mul, Int.sub_eq_add_neg, Int.one_mul]
split
next h =>
replace h := Int.le_of_sub_nonpos h
rw [Int.ofNat_le] at h
rw [Int.ofNat_sub h]
next h =>
have : ¬ (y : Int) x := by
intro h
replace h := Int.sub_nonpos_of_le h
contradiction
rw [Int.ofNat_le] at this
rw [Lean.Omega.Int.ofNat_sub_eq_zero this]
private theorem dvd_le_tight' {d p b₁ b₂ : Int} (hd : d > 0) (h₁ : d p + b₁) (h₂ : p + b₂ 0)
: p + (b₁ - d*((b₁-b₂) / d)) 0 := by
have k, h := h₁
@@ -1881,31 +1855,6 @@ theorem of_not_dvd (a b : Int) : a != 0 → ¬ (a b) → b % a > 0 := by
simp [h₁] at h₂
assumption
@[expose]
def le_of_le_cert (p q : Poly) (k : Nat) : Bool :=
q == p.addConst (- k)
theorem le_of_le (ctx : Context) (p q : Poly) (k : Nat)
: le_of_le_cert p q k p.denote' ctx 0 q.denote' ctx 0 := by
simp [le_of_le_cert]; intro; subst q; simp
intro h
simp [Lean.Omega.Int.add_le_zero_iff_le_neg']
exact Int.le_trans h (Int.ofNat_zero_le _)
@[expose]
def not_le_of_le_cert (p q : Poly) (k : Nat) : Bool :=
q == (p.mul (-1)).addConst (1 + k)
theorem not_le_of_le (ctx : Context) (p q : Poly) (k : Nat)
: not_le_of_le_cert p q k p.denote' ctx 0 ¬ q.denote' ctx 0 := by
simp [not_le_of_le_cert]; intro; subst q
intro h
apply Int.pos_of_neg_neg
apply Int.lt_of_add_one_le
simp [Int.neg_add]
rw [ Int.add_assoc, Int.add_assoc, Int.add_neg_cancel_right, Lean.Omega.Int.add_le_zero_iff_le_neg']
simp; exact Int.le_trans h (Int.ofNat_zero_le _)
@[expose]
def eq_def_cert (x : Var) (xPoly : Poly) (p : Poly) : Bool :=
p == .add (-1) x xPoly
@@ -1950,6 +1899,62 @@ theorem diseq_norm_poly (ctx : Context) (p p' : Poly) : p.denote' ctx = p'.denot
theorem dvd_norm_poly (ctx : Context) (d : Int) (p p' : Poly) : p.denote' ctx = p'.denote' ctx d p.denote' ctx d p'.denote' ctx := by
intro h; rw [h]; simp
/-!
Constraint propagation helper theorems.
-/
@[expose]
def le_of_le_cert (p₁ p₂ : Poly) : Bool :=
match p₁, p₂ with
| .add .., .num _ => false
| .num _, .add .. => false
| .num c₁, .num c₂ => c₁ c₂
| .add a₁ x₁ p₁, .add a₂ x₂ p₂ => a₁ == a₂ && x₁ == x₂ && le_of_le_cert p₁ p₂
theorem le_of_le' (ctx : Context) (p₁ p₂ : Poly) : le_of_le_cert p₁ p₂ k, p₁.denote' ctx k p₂.denote' ctx k := by
simp [Poly.denote'_eq_denote]
fun_induction le_of_le_cert <;> simp [Poly.denote]
next c₁ c₂ =>
intro h k h₁
exact Int.le_trans h h₁
next a₁ x₁ p₁ a₂ x₂ p₂ ih =>
intro _ _ h; subst a₁ x₁
replace ih := ih h; clear h
intro k h
replace h : p₁.denote ctx k - a₂ * x₂.denote ctx := by omega
replace ih := ih _ h
omega
theorem le_of_le (ctx : Context) (p₁ p₂ : Poly) : le_of_le_cert p₁ p₂ p₁.denote' ctx 0 p₂.denote' ctx 0 :=
fun h => le_of_le' ctx p₁ p₂ h 0
@[expose]
def not_le_of_le_cert (p₁ p₂ : Poly) : Bool :=
match p₁, p₂ with
| .add .., .num _ => false
| .num _, .add .. => false
| .num c₁, .num c₂ => c₁ 1 - c₂
| .add a₁ x₁ p₁, .add a₂ x₂ p₂ => a₁ == -a₂ && x₁ == x₂ && not_le_of_le_cert p₁ p₂
theorem not_le_of_le' (ctx : Context) (p₁ p₂ : Poly) : not_le_of_le_cert p₁ p₂ k, p₁.denote' ctx k ¬ (p₂.denote' ctx -k) := by
simp [Poly.denote'_eq_denote]
fun_induction not_le_of_le_cert <;> simp [Poly.denote]
next c₁ c₂ =>
intro h k h₁
omega
next a₁ x₁ p₁ a₂ x₂ p₂ ih =>
intro _ _ h; subst a₁ x₁
replace ih := ih h; clear h
intro k h
replace h : p₁.denote ctx k + a₂ * x₂.denote ctx := by rw [Int.neg_mul] at h; omega
replace ih := ih _ h
omega
theorem not_le_of_le (ctx : Context) (p₁ p₂ : Poly) : not_le_of_le_cert p₁ p₂ p₁.denote' ctx 0 ¬ (p₂.denote' ctx 0) := by
intro h h₁
have := not_le_of_le' ctx p₁ p₂ h 0 h₁; simp at this
simp [*]
end Int.Linear
theorem Int.not_le_eq (a b : Int) : (¬a b) = (b + 1 a) := by

View File

@@ -13,92 +13,91 @@ public import Init.Data.RArray
public section
namespace Int.OfNat
/-!
Helper definitions and theorems for converting `Nat` expressions into `Int` one.
We use them to implement the arithmetic theories in `grind`
-/
namespace Nat.ToInt
abbrev Var := Nat
abbrev Context := Lean.RArray Nat
@[expose]
def Var.denote (ctx : Context) (v : Var) : Nat :=
ctx.get v
theorem ofNat_toNat (a : Int) : (NatCast.natCast a.toNat : Int) = if a 0 then 0 else a := by simp [Int.max_def]
inductive Expr where
| num (v : Nat)
| var (i : Var)
| add (a b : Expr)
| mul (a b : Expr)
| div (a b : Expr)
| mod (a b : Expr)
| pow (a : Expr) (k : Nat)
deriving BEq
theorem toNat_nonneg (x : Nat) : (-1:Int) * (NatCast.natCast x) 0 := by simp
@[expose]
def Expr.denote (ctx : Context) : Expr Nat
| .num k => k
| .var v => v.denote ctx
| .add a b => Nat.add (denote ctx a) (denote ctx b)
| .mul a b => Nat.mul (denote ctx a) (denote ctx b)
| .div a b => Nat.div (denote ctx a) (denote ctx b)
| .mod a b => Nat.mod (denote ctx a) (denote ctx b)
| .pow a k => Nat.pow (denote ctx a) k
theorem natCast_ofNat (n : Nat) : (NatCast.natCast (OfNat.ofNat n : Nat) : Int) = OfNat.ofNat n := by rfl
@[expose]
def Expr.denoteAsInt (ctx : Context) : Expr Int
| .num k => Int.ofNat k
| .var v => Int.ofNat (v.denote ctx)
| .add a b => Int.add (denoteAsInt ctx a) (denoteAsInt ctx b)
| .mul a b => Int.mul (denoteAsInt ctx a) (denoteAsInt ctx b)
| .div a b => Int.ediv (denoteAsInt ctx a) (denoteAsInt ctx b)
| .mod a b => Int.emod (denoteAsInt ctx a) (denoteAsInt ctx b)
| .pow a k => Int.pow (denoteAsInt ctx a) k
theorem of_eq {a b : Nat} {a' b' : Int}
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : a = b a' = b' := by
intro h; replace h := congrArg (NatCast.natCast (R := Int)) h
rw [h₁, h₂] at h; assumption
theorem Expr.denoteAsInt_eq (ctx : Context) (e : Expr) : e.denoteAsInt ctx = e.denote ctx := by
induction e <;> simp [denote, denoteAsInt, *] <;> rfl
theorem of_diseq {a b : Nat} {a' b' : Int}
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : a b a' b' := by
intro hne h; rw [ h₁, h₂] at h
replace h := Int.ofNat_inj.mp h; contradiction
theorem Expr.eq_denoteAsInt (ctx : Context) (e : Expr) : e.denote ctx = e.denoteAsInt ctx := by
apply Eq.symm; apply denoteAsInt_eq
theorem of_dvd (d a : Nat) (d' a' : Int)
(h₁ : NatCast.natCast d = d') (h₂ : NatCast.natCast a = a') : d a d' a' := by
simp [ h₁, h₂, Int.ofNat_dvd]
theorem Expr.eq (ctx : Context) (lhs rhs : Expr)
: (lhs.denote ctx = rhs.denote ctx) = (lhs.denoteAsInt ctx = rhs.denoteAsInt ctx) := by
simp [denoteAsInt_eq, Int.ofNat_inj]
theorem of_le {a b : Nat} {a' b' : Int}
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : a b a' b' := by
intro h; replace h := Int.ofNat_le |>.mpr h
rw [ h₁, h₂]; assumption
theorem Expr.le (ctx : Context) (lhs rhs : Expr)
: (lhs.denote ctx rhs.denote ctx) = (lhs.denoteAsInt ctx rhs.denoteAsInt ctx) := by
simp [denoteAsInt_eq, Int.ofNat_le]
theorem of_not_le {a b : Nat} {a' b' : Int}
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : ¬ (a b) b' + 1 a' := by
intro h; rw [ Int.ofNat_le] at h
rw [ h₁, h₂]; show (b + 1 : Int) a; omega
theorem of_le (ctx : Context) (lhs rhs : Expr)
: lhs.denote ctx rhs.denote ctx lhs.denoteAsInt ctx rhs.denoteAsInt ctx := by
rw [Expr.le ctx lhs rhs]; simp
theorem add_congr {a b : Nat} {a' b' : Int}
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a + b) = a' + b' := by
simp_all [Int.natCast_add]
theorem of_not_le (ctx : Context) (lhs rhs : Expr)
: ¬ lhs.denote ctx rhs.denote ctx ¬ lhs.denoteAsInt ctx rhs.denoteAsInt ctx := by
rw [Expr.le ctx lhs rhs]; simp
theorem mul_congr {a b : Nat} {a' b' : Int}
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a * b) = a' * b' := by
simp_all [Int.natCast_mul]
theorem of_dvd (ctx : Context) (d : Nat) (e : Expr)
: d e.denote ctx Int.ofNat d e.denoteAsInt ctx := by
simp [Expr.denoteAsInt_eq, Int.ofNat_dvd]
theorem of_eq (ctx : Context) (lhs rhs : Expr)
: lhs.denote ctx = rhs.denote ctx lhs.denoteAsInt ctx = rhs.denoteAsInt ctx := by
rw [Expr.eq ctx lhs rhs]; simp
theorem of_not_eq (ctx : Context) (lhs rhs : Expr)
: ¬ lhs.denote ctx = rhs.denote ctx ¬ lhs.denoteAsInt ctx = rhs.denoteAsInt ctx := by
rw [Expr.eq ctx lhs rhs]; simp
theorem ofNat_toNat (a : Int) : (NatCast.natCast a.toNat : Int) = if a 0 then 0 else a := by
theorem sub_congr {a b : Nat} {a' b' : Int}
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a - b) = if b' + (-1)*a' 0 then a' - b' else 0 := by
rw [Int.neg_mul, Int.sub_eq_add_neg, Int.one_mul]
split
next h =>
rw [Int.toNat_of_nonpos h]; rfl
have h := Int.le_of_sub_nonpos h
simp [ h₁, h₂, Int.ofNat_le] at h
simp [Int.ofNat_sub h]
rw [ h₁, h₂]
next h =>
simp at h
have := Int.toNat_of_nonneg (Int.le_of_lt h)
assumption
have : ¬ (b : Int) a := by
intro h
replace h := Int.sub_nonpos_of_le h
simp [h₁, h₂] at h
contradiction
rw [Int.ofNat_le] at this
simp [Lean.Omega.Int.ofNat_sub_eq_zero this]
theorem Expr.denoteAsInt_nonneg (ctx : Context) (e : Expr) : 0 e.denoteAsInt ctx := by
simp [Expr.denoteAsInt_eq]
theorem pow_congr {a : Nat} (k : Nat) (a' : Int)
(h₁ : NatCast.natCast a = a') : NatCast.natCast (a ^ k) = a' ^ k := by
simp_all [Int.natCast_pow]
end Int.OfNat
theorem div_congr {a b : Nat} {a' b' : Int}
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a / b) = a' / b' := by
simp_all [Int.natCast_ediv]
theorem mod_congr {a b : Nat} {a' b' : Int}
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a % b) = a' % b' := by
simp_all [Int.natCast_emod]
end Nat.ToInt
namespace Int.Nonneg
@[expose] def num_cert (a : Int) : Bool := a 0
theorem num (a : Int) : num_cert a a 0 := by simp [num_cert]
theorem add (a b : Int) (h₁ : a 0) (h₂ : b 0) : a + b 0 := by exact Int.add_nonneg h₁ h₂
theorem mul (a b : Int) (h₁ : a 0) (h₂ : b 0) : a * b 0 := by exact Int.mul_nonneg h₁ h₂
theorem div (a b : Int) (h₁ : a 0) (h₂ : b 0) : a / b 0 := by exact Int.ediv_nonneg h₁ h₂
theorem pow (a : Int) (k : Nat) (h₁ : a 0) : a ^ k 0 := by exact Int.pow_nonneg h₁
theorem mod (a b : Int) (h₁ : a 0) : a % b 0 := by
by_cases b = 0
next => simp [*]
next h => exact emod_nonneg a h
theorem natCast (a : Nat) : (NatCast.natCast a : Int) 0 := by simp
theorem toPoly (e : Int) : e 0 -1 * e 0 := by omega
end Int.Nonneg

View File

@@ -1117,11 +1117,11 @@ protected theorem add_le_zero_iff_le_neg {a b : Int} : a + b ≤ 0 ↔ a ≤ -b
protected theorem add_le_zero_iff_le_neg' {a b : Int} : a + b 0 b -a := by
rw [Int.add_comm, Int.add_le_zero_iff_le_neg]
protected theorem add_nonnneg_iff_neg_le {a b : Int} : 0 a + b -b a := by
protected theorem add_nonneg_iff_neg_le {a b : Int} : 0 a + b -b a := by
rw [Int.le_add_iff_sub_le, Int.zero_sub]
protected theorem add_nonnneg_iff_neg_le' {a b : Int} : 0 a + b -a b := by
rw [Int.add_comm, Int.add_nonnneg_iff_neg_le]
protected theorem add_nonneg_iff_neg_le' {a b : Int} : 0 a + b -a b := by
rw [Int.add_comm, Int.add_nonneg_iff_neg_le]
/- ### Order properties and multiplication -/

View File

@@ -98,12 +98,12 @@ instance Attach.instIteratorCollectPartial {α β : Type w} {m : Type w → Type
.defaultImplementation
instance Attach.instIteratorLoop {α β : Type w} {m : Type w Type w'} [Monad m]
[Monad n] {P : β Prop} [Iterator α m β] [MonadLiftT m n] :
{n : Type x Type x'} [Monad n] {P : β Prop} [Iterator α m β] :
IteratorLoop (Attach α m P) m n :=
.defaultImplementation
instance Attach.instIteratorLoopPartial {α β : Type w} {m : Type w Type w'} [Monad m]
[Monad n] {P : β Prop} [Iterator α m β] [MonadLiftT m n] :
{n : Type x Type x'} [Monad n] {P : β Prop} [Iterator α m β] :
IteratorLoopPartial (Attach α m P) m n :=
.defaultImplementation

View File

@@ -231,14 +231,14 @@ instance {α β γ : Type w} {m : Type w → Type w'}
.defaultImplementation
instance FilterMap.instIteratorLoop {α β γ : Type w} {m : Type w Type w'}
{n : Type w Type w''} {o : Type w Type w'''}
{n : Type w Type w''} {o : Type x Type x'}
[Monad n] [Monad o] [Iterator α m β] {lift : α : Type w m α n α}
{f : β PostconditionT n (Option γ)} [Finite α m] :
IteratorLoop (FilterMap α m n lift f) n o :=
.defaultImplementation
instance FilterMap.instIteratorLoopPartial {α β γ : Type w} {m : Type w Type w'}
{n : Type w Type w''} {o : Type w Type w'''}
{n : Type w Type w''} {o : Type x Type x'}
[Monad n] [Monad o] [Iterator α m β] {lift : α : Type w m α n α}
{f : β PostconditionT n (Option γ)} :
IteratorLoopPartial (FilterMap α m n lift f) n o :=
@@ -274,14 +274,14 @@ instance Map.instIteratorCollectPartial {α β γ : Type w} {m : Type w → Type
it.internalState.inner (m := m)
instance Map.instIteratorLoop {α β γ : Type w} {m : Type w Type w'}
{n : Type w Type w''} {o : Type w Type x} [Monad n] [Monad o] [Iterator α m β]
{n : Type w Type w''} {o : Type x Type x'} [Monad n] [Monad o] [Iterator α m β]
{lift : α : Type w m α n α}
{f : β PostconditionT n γ} :
IteratorLoop (Map α m n lift f) n o :=
.defaultImplementation
instance Map.instIteratorLoopPartial {α β γ : Type w} {m : Type w Type w'}
{n : Type w Type w''} {o : Type w Type x} [Monad n] [Monad o] [Iterator α m β]
{n : Type w Type w''} {o : Type x Type x'} [Monad n] [Monad o] [Iterator α m β]
{lift : α : Type w m α n α}
{f : β PostconditionT n γ} :
IteratorLoopPartial (Map α m n lift f) n o :=

View File

@@ -123,15 +123,16 @@ instance Types.ULiftIterator.instProductive [Iterator α m β] [Productive α m]
Productive (ULiftIterator α m n β lift) n :=
.of_productivenessRelation instProductivenessRelation
instance Types.ULiftIterator.instIteratorLoop {o} [Monad n] [Monad o] [Iterator α m β] :
instance Types.ULiftIterator.instIteratorLoop {o : Type x Type x'} [Monad n] [Monad o]
[Iterator α m β] :
IteratorLoop (ULiftIterator α m n β lift) n o :=
.defaultImplementation
instance Types.ULiftIterator.instIteratorLoopPartial {o} [Monad n] [Monad o] [Iterator α m β] :
instance Types.ULiftIterator.instIteratorLoopPartial {o : Type x Type x'} [Monad n] [Monad o] [Iterator α m β] :
IteratorLoopPartial (ULiftIterator α m n β lift) n o :=
.defaultImplementation
instance Types.ULiftIterator.instIteratorCollect {o} [Monad n] [Monad o] [Iterator α m β] :
instance Types.ULiftIterator.instIteratorCollect [Monad n] [Monad o] [Iterator α m β] :
IteratorCollect (ULiftIterator α m n β lift) n o :=
.defaultImplementation

View File

@@ -12,4 +12,6 @@ public import Init.Data.Iterators.Consumers.Collect
public import Init.Data.Iterators.Consumers.Loop
public import Init.Data.Iterators.Consumers.Partial
public import Init.Data.Iterators.Consumers.Stream
public section

View File

@@ -6,12 +6,11 @@ Authors: Paul Reichert
module
prelude
public import Init.Data.Stream
public import Init.Data.Iterators.Consumers.Partial
public import Init.Data.Iterators.Consumers.Loop
public import Init.Data.Iterators.Consumers.Monadic.Access
public section
@[expose] public section
namespace Std.Iterators
@@ -64,15 +63,4 @@ def Iter.atIdx? {α β} [Iterator α Id β] [Productive α Id] [IteratorAccess
| .skip _ => none
| .done => none
instance {α β} [Iterator α Id β] [Productive α Id] [IteratorAccess α Id] :
Stream (Iter (α := α) β) β where
next? it := match (it.toIterM.nextAtIdx? 0).run with
| .yield it' out _ => some (out, it'.toIter)
| .skip _ h => False.elim ?noskip
| .done _ => none
where finally
case noskip =>
revert h
exact IterM.not_isPlausibleNthOutputStep_yield
end Std.Iterators

View File

@@ -10,7 +10,7 @@ public import Init.Data.Iterators.Basic
public import Init.Data.Iterators.Consumers.Partial
public import Init.Data.Iterators.Consumers.Monadic.Collect
public section
@[expose] public section
/-!
# Collectors

View File

@@ -33,32 +33,42 @@ so this is not marked as `instance`. This way, more convenient instances can be
or future library improvements will make it more comfortable.
-/
@[always_inline, inline]
def Iter.instForIn' {α : Type w} {β : Type w} {n : Type w Type w'} [Monad n]
def Iter.instForIn' {α : Type w} {β : Type w} {n : Type x Type x'} [Monad n]
[Iterator α Id β] [Finite α Id] [IteratorLoop α Id n] :
ForIn' n (Iter (α := α) β) β fun it out => it.IsPlausibleIndirectOutput out where
forIn' it init f :=
IteratorLoop.finiteForIn' (fun δ (c : Id δ) => pure c.run) |>.forIn' it.toIterM init
IteratorLoop.finiteForIn' (fun _ _ f c => f c.run) |>.forIn' it.toIterM init
fun out h acc =>
f out (Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM.mpr h) acc
instance (α : Type w) (β : Type w) (n : Type w Type w') [Monad n]
instance (α : Type w) (β : Type w) (n : Type x Type x') [Monad n]
[Iterator α Id β] [Finite α Id] [IteratorLoop α Id n] :
ForIn n (Iter (α := α) β) β :=
haveI : ForIn' n (Iter (α := α) β) β _ := Iter.instForIn'
instForInOfForIn'
instance (α : Type w) (β : Type w) (n : Type w Type w') [Monad n]
@[always_inline, inline]
def Iter.Partial.instForIn' {α : Type w} {β : Type w} {n : Type x Type x'} [Monad n]
[Iterator α Id β] [IteratorLoopPartial α Id n] :
ForIn n (Iter.Partial (α := α) β) β where
forIn it init f :=
ForIn.forIn it.it.toIterM.allowNontermination init f
ForIn' n (Iter.Partial (α := α) β) β fun it out => it.it.IsPlausibleIndirectOutput out where
forIn' it init f :=
IteratorLoopPartial.forInPartial (α := α) (m := Id) (n := n) (fun _ _ f c => f c.run)
it.it.toIterM init
fun out h acc =>
f out (Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM.mpr h) acc
instance {m : Type w Type w'}
instance (α : Type w) (β : Type w) (n : Type x Type x') [Monad n]
[Iterator α Id β] [IteratorLoopPartial α Id n] :
ForIn n (Iter.Partial (α := α) β) β :=
haveI : ForIn' n (Iter.Partial (α := α) β) β _ := Iter.Partial.instForIn'
instForInOfForIn'
instance {m : Type x Type x'}
{α : Type w} {β : Type w} [Iterator α Id β] [Finite α Id] [IteratorLoop α Id m] :
ForM m (Iter (α := α) β) β where
forM it f := forIn it PUnit.unit (fun out _ => do f out; return .yield .unit)
instance {m : Type w Type w'}
instance {m : Type x Type x'}
{α : Type w} {β : Type w} [Iterator α Id β] [Finite α Id] [IteratorLoopPartial α Id m] :
ForM m (Iter.Partial (α := α) β) β where
forM it f := forIn it PUnit.unit (fun out _ => do f out; return .yield .unit)
@@ -75,8 +85,8 @@ number of steps. If the iterator is not finite or such an instance is not availa
verify the behavior of the partial variant.
-/
@[always_inline, inline]
def Iter.foldM {m : Type w Type w'} [Monad m]
{α : Type w} {β : Type w} {γ : Type w} [Iterator α Id β] [Finite α Id]
def Iter.foldM {m : Type x Type x'} [Monad m]
{α : Type w} {β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id m] (f : γ β m γ)
(init : γ) (it : Iter (α := α) β) : m γ :=
ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x)
@@ -91,8 +101,8 @@ This is a partial, potentially nonterminating, function. It is not possible to f
its behavior. If the iterator has a `Finite` instance, consider using `IterM.foldM` instead.
-/
@[always_inline, inline]
def Iter.Partial.foldM {m : Type w Type w'} [Monad m]
{α : Type w} {β : Type w} {γ : Type w} [Iterator α Id β]
def Iter.Partial.foldM {m : Type x Type x'} [Monad m]
{α : Type w} {β : Type w} {γ : Type x} [Iterator α Id β]
[IteratorLoopPartial α Id m] (f : γ β m γ)
(init : γ) (it : Iter.Partial (α := α) β) : m γ :=
ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x)
@@ -109,7 +119,7 @@ number of steps. If the iterator is not finite or such an instance is not availa
verify the behavior of the partial variant.
-/
@[always_inline, inline]
def Iter.fold {α : Type w} {β : Type w} {γ : Type w} [Iterator α Id β] [Finite α Id]
def Iter.fold {α : Type w} {β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] (f : γ β γ)
(init : γ) (it : Iter (α := α) β) : γ :=
ForIn.forIn (m := Id) it init (fun x acc => ForInStep.yield (f acc x))
@@ -124,7 +134,7 @@ This is a partial, potentially nonterminating, function. It is not possible to f
its behavior. If the iterator has a `Finite` instance, consider using `IterM.fold` instead.
-/
@[always_inline, inline]
def Iter.Partial.fold {α : Type w} {β : Type w} {γ : Type w} [Iterator α Id β]
def Iter.Partial.fold {α : Type w} {β : Type w} {γ : Type x} [Iterator α Id β]
[IteratorLoopPartial α Id Id] (f : γ β γ)
(init : γ) (it : Iter.Partial (α := α) β) : γ :=
ForIn.forIn (m := Id) it init (fun x acc => ForInStep.yield (f acc x))

View File

@@ -9,7 +9,7 @@ prelude
public import Init.Data.Iterators.Consumers.Monadic.Partial
public import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
public section
@[expose] public section
/-!
# Collectors

View File

@@ -9,6 +9,7 @@ prelude
public import Init.RCases
public import Init.Data.Iterators.Basic
public import Init.Data.Iterators.Consumers.Monadic.Partial
public import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
public section
@@ -32,6 +33,8 @@ asserts that an `IteratorLoop` instance equals the default implementation.
namespace Std.Iterators
open Std.Internal
section Typeclasses
/--
@@ -39,6 +42,7 @@ Relation that needs to be well-formed in order for a loop over an iterator to te
It is assumed that the `plausible_forInStep` predicate relates the input and output of the
stepper function.
-/
@[expose]
def IteratorLoop.rel (α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β]
{γ : Type x} (plausible_forInStep : β γ ForInStep γ Prop)
(p' p : IterM (α := α) m β × γ) : Prop :=
@@ -48,6 +52,7 @@ def IteratorLoop.rel (α : Type w) (m : Type w → Type w') {β : Type w} [Itera
/--
Asserts that `IteratorLoop.rel` is well-founded.
-/
@[expose]
def IteratorLoop.WellFounded (α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β]
{γ : Type x} (plausible_forInStep : β γ ForInStep γ Prop) : Prop :=
_root_.WellFounded (IteratorLoop.rel α m plausible_forInStep)
@@ -61,9 +66,10 @@ This class is experimental and users of the iterator API should not explicitly d
They can, however, assume that consumers that require an instance will work for all iterators
provided by the standard library.
-/
@[ext]
class IteratorLoop (α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β]
(n : Type w Type w'') where
forIn : (_lift : (γ : Type w) m γ n γ) (γ : Type w),
(n : Type x Type x') where
forIn : (_liftBind : (γ : Type w) (δ : Type x) (γ n δ) m γ n δ) (γ : Type x),
(plausible_forInStep : β γ ForInStep γ Prop)
IteratorLoop.WellFounded α m plausible_forInStep
(it : IterM (α := α) m β) γ
@@ -79,8 +85,8 @@ They can, however, assume that consumers that require an instance will work for
provided by the standard library.
-/
class IteratorLoopPartial (α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β]
(n : Type w Type w'') where
forInPartial : (_lift : (γ : Type w) m γ n γ) {γ : Type w},
(n : Type x Type x') where
forInPartial : (_liftBind : (γ : Type w) (δ : Type x) (γ n δ) m γ n δ) {γ : Type x},
(it : IterM (α := α) m β) γ
((b : β) it.IsPlausibleIndirectOutput b (c : γ) n (ForInStep γ)) n γ
@@ -108,43 +114,36 @@ class IteratorSizePartial (α : Type w) (m : Type w → Type w') {β : Type w} [
end Typeclasses
/-- Internal implementation detail of the iterator library. -/
def IteratorLoop.WFRel {α : Type w} {m : Type w Type w'} {β : Type w} [Iterator α m β]
{γ : Type x} {plausible_forInStep : β γ ForInStep γ Prop}
(_wf : WellFounded α m plausible_forInStep) :=
IterM (α := α) m β × γ
structure IteratorLoop.WithWF (α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β]
{γ : Type x} (PlausibleForInStep : β γ ForInStep γ Prop)
(hwf : IteratorLoop.WellFounded α m PlausibleForInStep) where
it : IterM (α := α) m β
acc : γ
/-- Internal implementation detail of the iterator library. -/
def IteratorLoop.WFRel.mk {α : Type w} {m : Type w Type w'} {β : Type w} [Iterator α m β]
{γ : Type x} {plausible_forInStep : β γ ForInStep γ Prop}
(wf : WellFounded α m plausible_forInStep) (it : IterM (α := α) m β) (c : γ) :
IteratorLoop.WFRel wf :=
(it, c)
private instance {α : Type w} {m : Type w Type w'} {β : Type w} [Iterator α m β]
{γ : Type x} {plausible_forInStep : β γ ForInStep γ Prop}
(wf : IteratorLoop.WellFounded α m plausible_forInStep) :
WellFoundedRelation (IteratorLoop.WFRel wf) where
rel := IteratorLoop.rel α m plausible_forInStep
wf := wf
instance IteratorLoop.WithWF.instWellFoundedRelation
(α : Type w) (m : Type w Type w') {β : Type w} [Iterator α m β]
{γ : Type x} (PlausibleForInStep : β γ ForInStep γ Prop)
(hwf : IteratorLoop.WellFounded α m PlausibleForInStep) :
WellFoundedRelation (WithWF α m PlausibleForInStep hwf) where
rel := InvImage (IteratorLoop.rel α m PlausibleForInStep) (fun x => (x.it, x.acc))
wf := by exact InvImage.wf _ hwf
/--
This is the loop implementation of the default instance `IteratorLoop.defaultImplementation`.
-/
@[specialize]
@[specialize, expose]
def IterM.DefaultConsumers.forIn' {m : Type w Type w'} {α : Type w} {β : Type w}
[Iterator α m β]
{n : Type w Type w''} [Monad n]
(lift : γ, m γ n γ) (γ : Type w)
{n : Type x Type x'} [Monad n]
(lift : γ δ, (γ n δ) m γ n δ) (γ : Type x)
(plausible_forInStep : β γ ForInStep γ Prop)
(wf : IteratorLoop.WellFounded α m plausible_forInStep)
(it : IterM (α := α) m β) (init : γ)
(P : β Prop) (hP : b, it.IsPlausibleIndirectOutput b P b)
(f : (b : β) P b (c : γ) n (Subtype (plausible_forInStep b c))) : n γ :=
haveI : WellFounded _ := wf
letI : MonadLift m n := fun {γ} => lift γ
do
match it.step with
| .yield it' out h =>
(lift _ _ · it.step) fun
| .yield it' out h => do
match f out (hP _ <| .direct _, h) init with
| .yield c, _ =>
IterM.DefaultConsumers.forIn' lift _ plausible_forInStep wf it' c P
@@ -154,18 +153,50 @@ def IterM.DefaultConsumers.forIn' {m : Type w → Type w'} {α : Type w} {β : T
IterM.DefaultConsumers.forIn' lift _ plausible_forInStep wf it' init P
(fun _ h' => hP _ <| .indirect _, rfl, h h') f
| .done _ => return init
termination_by IteratorLoop.WFRel.mk wf it init
termination_by IteratorLoop.WithWF.mk it init (hwf := wf)
decreasing_by
· exact Or.inl out, _, _
· exact Or.inr _, rfl
theorem IterM.DefaultConsumers.forIn'_eq_forIn' {m : Type w Type w'} {α : Type w} {β : Type w}
[Iterator α m β]
{n : Type x Type x'} [Monad n]
{lift : γ δ, (γ n δ) m γ n δ} {γ : Type x}
{Pl : β γ ForInStep γ Prop}
{wf : IteratorLoop.WellFounded α m Pl}
{it : IterM (α := α) m β} {init : γ}
{P : β Prop} {hP : b, it.IsPlausibleIndirectOutput b P b}
{Q : β Prop} {hQ : b, it.IsPlausibleIndirectOutput b Q b}
{f : (b : β) P b (c : γ) n (Subtype (Pl b c))}
{g : (b : β) Q b (c : γ) n (Subtype (Pl b c))}
(hfg : b c, (hPb : P b) (hQb : Q b) f b hPb c = g b hQb c) :
IterM.DefaultConsumers.forIn' lift γ Pl wf it init P hP f =
IterM.DefaultConsumers.forIn' lift γ Pl wf it init Q hQ g := by
rw [forIn', forIn']
congr; ext step
split
· congr
· apply hfg
· ext
split
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
assumption
· rfl
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
assumption
· rfl
termination_by IteratorLoop.WithWF.mk it init (hwf := wf)
decreasing_by
· exact Or.inl _, _, _
· exact Or.inr _, rfl
/--
This is the default implementation of the `IteratorLoop` class.
It simply iterates through the iterator using `IterM.step`. For certain iterators, more efficient
implementations are possible and should be used instead.
-/
@[always_inline, inline]
def IteratorLoop.defaultImplementation {α : Type w} {m : Type w Type w'} {n : Type w Type w''}
@[always_inline, inline, expose]
def IteratorLoop.defaultImplementation {α : Type w} {m : Type w Type w'} {n : Type x Type x'}
[Monad n] [Iterator α m β] :
IteratorLoop α m n where
forIn lift γ Pl wf it init := IterM.DefaultConsumers.forIn' lift γ Pl wf it init _ (fun _ => id)
@@ -174,9 +205,10 @@ def IteratorLoop.defaultImplementation {α : Type w} {m : Type w → Type w'} {n
Asserts that a given `IteratorLoop` instance is equal to `IteratorLoop.defaultImplementation`.
(Even though equal, the given instance might be vastly more efficient.)
-/
class LawfulIteratorLoop (α : Type w) (m : Type w Type w') (n : Type w Type w'')
[Monad n] [Iterator α m β] [Finite α m] [i : IteratorLoop α m n] where
lawful : i = .defaultImplementation
class LawfulIteratorLoop (α : Type w) (m : Type w Type w') (n : Type x Type x')
[Monad m] [Monad n] [Iterator α m β] [i : IteratorLoop α m n] where
lawful : lift [LawfulMonadLiftBindFunction lift], i.forIn lift =
IteratorLoop.defaultImplementation.forIn lift
/--
This is the loop implementation of the default instance `IteratorLoopPartial.defaultImplementation`.
@@ -184,23 +216,21 @@ This is the loop implementation of the default instance `IteratorLoopPartial.def
@[specialize]
partial def IterM.DefaultConsumers.forInPartial {m : Type w Type w'} {α : Type w} {β : Type w}
[Iterator α m β]
{n : Type w Type w''} [Monad n]
(lift : γ, m γ n γ) (γ : Type w)
{n : Type x Type x'} [Monad n]
(lift : γ δ, (γ n δ) m γ n δ) (γ : Type x)
(it : IterM (α := α) m β) (init : γ)
(f : (b : β) it.IsPlausibleIndirectOutput b (c : γ) n (ForInStep γ)) : n γ :=
letI : MonadLift m n := fun {γ} => lift γ
do
match it.step with
| .yield it' out h =>
match f out (.direct _, h) init with
| .yield c =>
IterM.DefaultConsumers.forInPartial lift _ it' c
(lift _ _ · it.step) fun
| .yield it' out h => do
match f out (.direct _, h) init with
| .yield c =>
IterM.DefaultConsumers.forInPartial lift _ it' c
fun out h' acc => f out (.indirect _, rfl, h h') acc
| .done c => return c
| .skip it' h =>
IterM.DefaultConsumers.forInPartial lift _ it' init
fun out h' acc => f out (.indirect _, rfl, h h') acc
| .done c => return c
| .skip it' h =>
IterM.DefaultConsumers.forInPartial lift _ it' init
fun out h' acc => f out (.indirect _, rfl, h h') acc
| .done _ => return init
| .done _ => return init
/--
This is the default implementation of the `IteratorLoopPartial` class.
@@ -209,19 +239,19 @@ implementations are possible and should be used instead.
-/
@[always_inline, inline]
def IteratorLoopPartial.defaultImplementation {α : Type w} {m : Type w Type w'}
{n : Type w Type w''} [Monad m] [Monad n] [Iterator α m β] :
{n : Type x Type x'} [Monad m] [Monad n] [Iterator α m β] :
IteratorLoopPartial α m n where
forInPartial lift := IterM.DefaultConsumers.forInPartial lift _
instance (α : Type w) (m : Type w Type w') (n : Type w Type w'')
instance (α : Type w) (m : Type w Type w') (n : Type x Type x')
[Monad m] [Monad n] [Iterator α m β] [Finite α m] :
letI : IteratorLoop α m n := .defaultImplementation
LawfulIteratorLoop α m n :=
letI : IteratorLoop α m n := .defaultImplementation
rfl
fun _ => rfl
theorem IteratorLoop.wellFounded_of_finite {m : Type w Type w'}
{α β γ : Type w} [Iterator α m β] [Finite α m] :
{α β : Type w} {γ : Type x} [Iterator α m β] [Finite α m] :
WellFounded α m (γ := γ) fun _ _ _ => True := by
apply Subrelation.wf
(r := InvImage IterM.TerminationMeasures.Finite.Rel (fun p => p.1.finitelyManySteps))
@@ -237,9 +267,9 @@ theorem IteratorLoop.wellFounded_of_finite {m : Type w → Type w'}
This `ForIn'`-style loop construct traverses a finite iterator using an `IteratorLoop` instance.
-/
@[always_inline, inline]
def IteratorLoop.finiteForIn' {m : Type w Type w'} {n : Type w Type w''}
def IteratorLoop.finiteForIn' {m : Type w Type w'} {n : Type x Type x'}
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]
(lift : γ, m γ n γ) :
(lift : γ δ, (γ n δ) m γ n δ) :
ForIn' n (IterM (α := α) m β) β fun it out => it.IsPlausibleIndirectOutput out where
forIn' {γ} [Monad n] it init f :=
IteratorLoop.forIn (α := α) (m := m) lift γ (fun _ _ _ => True)
@@ -253,23 +283,30 @@ or future library improvements will make it more comfortable.
-/
@[always_inline, inline]
def IterM.instForIn' {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n] [Monad n]
[MonadLiftT m n] :
ForIn' n (IterM (α := α) m β) β fun it out => it.IsPlausibleIndirectOutput out :=
IteratorLoop.finiteForIn' (fun _ => monadLift)
IteratorLoop.finiteForIn' (fun _ _ f x => monadLift x >>= f)
instance {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]
[MonadLiftT m n] :
[MonadLiftT m n] [Monad n] :
ForIn n (IterM (α := α) m β) β :=
haveI : ForIn' n (IterM (α := α) m β) β _ := IterM.instForIn'
instForInOfForIn'
instance {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoopPartial α m n] [MonadLiftT m n] :
@[always_inline, inline]
def IterM.Partial.instForIn' {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoopPartial α m n] [MonadLiftT m n] [Monad n] :
ForIn' n (IterM.Partial (α := α) m β) β fun it out => it.it.IsPlausibleIndirectOutput out where
forIn' it init f :=
IteratorLoopPartial.forInPartial (α := α) (m := m) (fun _ => monadLift) it.it init f
forIn' it init f := IteratorLoopPartial.forInPartial (α := α) (m := m) (n := n)
(fun _ _ f x => monadLift x >>= f) it.it init f
instance {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoopPartial α m n] [MonadLiftT m n] [Monad n] :
ForIn n (IterM.Partial (α := α) m β) β :=
haveI : ForIn' n (IterM.Partial (α := α) m β) β _ := IterM.Partial.instForIn'
instForInOfForIn'
instance {m : Type w Type w'} {n : Type w Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]

View File

@@ -0,0 +1,27 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
public import Init.Data.Stream
public import Init.Data.Iterators.Consumers.Access
public section
namespace Std.Iterators
instance {α β} [Iterator α Id β] [Productive α Id] [IteratorAccess α Id] :
Stream (Iter (α := α) β) β where
next? it := match (it.toIterM.nextAtIdx? 0).run with
| .yield it' out _ => some (out, it'.toIter)
| .skip _ h => False.elim ?noskip
| .done _ => none
where finally
case noskip =>
revert h
exact IterM.not_isPlausibleNthOutputStep_yield
end Std.Iterators

View File

@@ -24,6 +24,12 @@ the requirement that the `MonadLift(T)` instance induced by `f` admits a
namespace Std.Internal
class LawfulMonadLiftBindFunction {m : Type u Type v} {n : Type w Type x} [Monad m]
[Monad n] (liftBind : γ δ, (γ n δ) m γ n δ) where
liftBind_pure {γ δ} (f : γ n δ) (a : γ) : liftBind γ δ f (pure a) = f a
liftBind_bind {β γ δ} (f : γ n δ) (x : m β) (g : β m γ) :
liftBind γ δ f (x >>= g) = liftBind β δ (fun b => liftBind γ δ f (g b)) x
class LawfulMonadLiftFunction {m : Type u Type v} {n : Type u Type w}
[Monad m] [Monad n] (lift : α : Type u m α n α) where
lift_pure {α : Type u} (a : α) : lift (pure a) = pure a
@@ -79,4 +85,35 @@ instance [LawfulMonadLiftFunction lift] :
{ monadLift_pure := LawfulMonadLiftFunction.lift_pure
monadLift_bind := LawfulMonadLiftFunction.lift_bind }
section LiftBind
variable {liftBind : γ δ, (γ m δ) m γ m δ}
instance [LawfulMonadLiftBindFunction (n := n) (fun _ _ f x => lift x >>= f)] [LawfulMonad n] :
LawfulMonadLiftFunction lift where
lift_pure {γ} a := by
simpa using LawfulMonadLiftBindFunction.liftBind_pure (n := n)
(liftBind := fun _ _ f x => lift x >>= f) (γ := γ) (δ := γ) pure a
lift_bind {β γ} x g := by
simpa using LawfulMonadLiftBindFunction.liftBind_bind (n := n)
(liftBind := fun _ _ f x => lift x >>= f) (β := β) (γ := γ) (δ := γ) pure x g
def LawfulMonadLiftBindFunction.id [Monad m] [LawfulMonad m] :
LawfulMonadLiftBindFunction (m := Id) (n := m) (fun _ _ f x => f x.run) where
liftBind_pure := by simp
liftBind_bind := by simp
instance {m : Type u Type v} [Monad m] {n : Type u Type w} [Monad n] [MonadLiftT m n]
[LawfulMonadLiftT m n] [LawfulMonad n] :
LawfulMonadLiftBindFunction (fun γ δ (f : γ n δ) (x : m γ) => monadLift x >>= f) where
liftBind_pure := by simp
liftBind_bind := by simp
instance {n : Type u Type w} [Monad n] [LawfulMonad n] :
LawfulMonadLiftBindFunction (fun γ δ (f : γ n δ) (x : Id γ) => f x.run) where
liftBind_pure := by simp
liftBind_bind := by simp
end LiftBind
end Std.Internal

View File

@@ -6,6 +6,7 @@ Authors: Paul Reichert
module
prelude
public import Init.Control.Lawful.MonadLift.Instances
public import Init.Data.Iterators.Lemmas.Consumers.Collect
public import all Init.Data.Iterators.Lemmas.Consumers.Monadic.Loop
public import all Init.Data.Iterators.Consumers.Loop
@@ -16,27 +17,28 @@ public section
namespace Std.Iterators
theorem Iter.forIn'_eq {α β : Type w} [Iterator α Id β] [Finite α Id]
{m : Type w Type w''} [Monad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{m : Type x Type x'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : (b : β) it.IsPlausibleIndirectOutput b γ m (ForInStep γ)} :
letI : ForIn' m (Iter (α := α) β) β _ := Iter.instForIn'
ForIn'.forIn' it init f =
IterM.DefaultConsumers.forIn' (fun _ c => pure c.run) γ (fun _ _ _ => True)
IterM.DefaultConsumers.forIn' (fun _ _ f x => f x.run) γ (fun _ _ _ => True)
IteratorLoop.wellFounded_of_finite it.toIterM init _ (fun _ => id)
(fun out h acc => (·, .intro) <$>
f out (Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM.mpr h) acc) := by
cases hl.lawful; rfl
simp [instForIn', ForIn'.forIn', IteratorLoop.finiteForIn', hl.lawful (fun γ δ f x => f x.run),
IteratorLoop.defaultImplementation]
theorem Iter.forIn_eq {α β : Type w} [Iterator α Id β] [Finite α Id]
{m : Type w Type w''} [Monad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{m : Type x Type x'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[hl : LawfulIteratorLoop α Id m] {γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : (b : β) γ m (ForInStep γ)} :
ForIn.forIn it init f =
IterM.DefaultConsumers.forIn' (fun _ c => pure c.run) γ (fun _ _ _ => True)
IterM.DefaultConsumers.forIn' (fun _ _ f c => f c.run) γ (fun _ _ _ => True)
IteratorLoop.wellFounded_of_finite it.toIterM init _ (fun _ => id)
(fun out _ acc => (·, .intro) <$>
f out acc) := by
cases hl.lawful; rfl
simp [ForIn.forIn, forIn'_eq, -forIn'_eq_forIn]
theorem Iter.forIn'_eq_forIn'_toIterM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
@@ -48,7 +50,7 @@ theorem Iter.forIn'_eq_forIn'_toIterM {α β : Type w} [Iterator α Id β]
letI : ForIn' m (IterM (α := α) Id β) β _ := IterM.instForIn'
ForIn'.forIn' it.toIterM init
(fun out h acc => f out (isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM.mpr h) acc) := by
rfl
simp [ForIn'.forIn', Iter.instForIn', IterM.instForIn', monadLift]
theorem Iter.forIn_eq_forIn_toIterM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
@@ -57,12 +59,12 @@ theorem Iter.forIn_eq_forIn_toIterM {α β : Type w} [Iterator α Id β]
{f : β γ m (ForInStep γ)} :
ForIn.forIn it init f =
ForIn.forIn it.toIterM init f := by
rfl
simp [forIn_eq_forIn', forIn'_eq_forIn'_toIterM, -forIn'_eq_forIn]
theorem Iter.forIn'_eq_match_step {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : (out : β) _ γ m (ForInStep γ)} :
letI : ForIn' m (Iter (α := α) β) β _ := Iter.instForIn'
ForIn'.forIn' it init f = (do
@@ -77,20 +79,27 @@ theorem Iter.forIn'_eq_match_step {α β : Type w} [Iterator α Id β]
ForIn'.forIn' it' init
fun out h' acc => f out (.indirect _, rfl, h h') acc
| .done _ => return init) := by
rw [Iter.forIn'_eq_forIn'_toIterM, @IterM.forIn'_eq_match_step, Iter.step]
simp only [liftM, monadLift, pure_bind]
generalize it.toIterM.step = step
cases step using PlausibleIterStep.casesOn
· apply bind_congr
simp only [forIn'_eq]
rw [IterM.DefaultConsumers.forIn'_eq_match_step]
simp only [bind_map_left, Iter.step]
cases it.toIterM.step.run using PlausibleIterStep.casesOn
· simp only [IterM.Step.toPure_yield, PlausibleIterStep.yield, toIter_toIterM, toIterM_toIter]
apply bind_congr
intro forInStep
rfl
· rfl
· rfl
cases forInStep
· simp
· simp only
apply IterM.DefaultConsumers.forIn'_eq_forIn'
intros; congr
· simp only
apply IterM.DefaultConsumers.forIn'_eq_forIn'
intros; congr
· simp
theorem Iter.forIn_eq_match_step {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : β γ m (ForInStep γ)} :
ForIn.forIn it init f = (do
match it.step with
@@ -100,23 +109,15 @@ theorem Iter.forIn_eq_match_step {α β : Type w} [Iterator α Id β]
| .done c => return c
| .skip it' _ => ForIn.forIn it' init f
| .done _ => return init) := by
rw [Iter.forIn_eq_forIn_toIterM, @IterM.forIn_eq_match_step, Iter.step]
simp only [liftM, monadLift, pure_bind]
generalize it.toIterM.step = step
cases step using PlausibleIterStep.casesOn
· apply bind_congr
intro forInStep
rfl
· rfl
· rfl
simp only [forIn_eq_forIn']
exact forIn'_eq_match_step
private theorem Iter.forIn'_toList.aux {ρ : Type u} {α : Type v} {γ : Type w} {m : Type w Type w'}
private theorem Iter.forIn'_toList.aux {ρ : Type u} {α : Type v} {γ : Type x} {m : Type x Type x'}
[Monad m] {_ : Membership α ρ} [ForIn' m ρ α inferInstance]
{r s : ρ} {init : γ} {f : (a : α) _ γ m (ForInStep γ)} (h : r = s) :
forIn' r init f = forIn' s init (fun a h' acc => f a (h h') acc) := by
cases h; rfl
theorem Iter.isPlausibleStep_iff_step_eq {α β} [Iterator α Id β]
[IteratorCollect α Id Id] [Finite α Id]
[LawfulIteratorCollect α Id Id] [LawfulDeterministicIterator α Id]
@@ -185,11 +186,11 @@ theorem Iter.mem_toList_iff_isPlausibleIndirectOutput {α β} [Iterator α Id β
simp [heq, IterStep.successor] at h₁
theorem Iter.forIn'_toList {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
[LawfulDeterministicIterator α Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : (out : β) _ γ m (ForInStep γ)} :
letI : ForIn' m (Iter (α := α) β) β _ := Iter.instForIn'
ForIn'.forIn' it.toList init f = ForIn'.forIn' it init (fun out h acc => f out (Iter.mem_toList_iff_isPlausibleIndirectOutput.mpr h) acc) := by
@@ -219,11 +220,11 @@ theorem Iter.forIn'_toList {α β : Type w} [Iterator α Id β]
· simp
theorem Iter.forIn'_eq_forIn'_toList {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
[LawfulDeterministicIterator α Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : (out : β) _ γ m (ForInStep γ)} :
letI : ForIn' m (Iter (α := α) β) β _ := Iter.instForIn'
ForIn'.forIn' it init f = ForIn'.forIn' it.toList init (fun out h acc => f out (Iter.mem_toList_iff_isPlausibleIndirectOutput.mp h) acc) := by
@@ -231,10 +232,10 @@ theorem Iter.forIn'_eq_forIn'_toList {α β : Type w} [Iterator α Id β]
congr
theorem Iter.forIn_toList {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : β γ m (ForInStep γ)} :
ForIn.forIn it.toList init f = ForIn.forIn it init f := by
rw [List.forIn_eq_foldlM]
@@ -250,14 +251,14 @@ theorem Iter.forIn_toList {α β : Type w} [Iterator α Id β]
cases forInStep
· induction it'.toList <;> simp [*]
· simp only [ForIn.forIn] at ihy
simp [ihy h, forIn_eq_forIn_toIterM]
simp [ihy h]
· rename_i it' h
simp only [bind_pure_comp]
rw [ihs h]
· simp
theorem Iter.foldM_eq_forIn {α β γ : Type w} [Iterator α Id β] [Finite α Id] {m : Type w Type w'}
[Monad m] [IteratorLoop α Id m] {f : γ β m γ}
theorem Iter.foldM_eq_forIn {α β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
{m : Type x Type x'} [Monad m] [IteratorLoop α Id m] {f : γ β m γ}
{init : γ} {it : Iter (α := α) β} :
it.foldM (init := init) f = ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x) :=
(rfl)
@@ -266,19 +267,19 @@ theorem Iter.foldM_eq_foldM_toIterM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ} {f : γ β m γ} :
it.foldM (init := init) f = it.toIterM.foldM (init := init) f :=
(rfl)
it.foldM (init := init) f = it.toIterM.foldM (init := init) f := by
simp [foldM_eq_forIn, IterM.foldM_eq_forIn, forIn_eq_forIn_toIterM]
theorem Iter.forIn_yield_eq_foldM {α β γ δ : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
theorem Iter.forIn_yield_eq_foldM {α β : Type w} {γ : Type x} {δ : Type x} [Iterator α Id β]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[LawfulIteratorLoop α Id m] {f : β γ m δ} {g : β γ δ γ} {init : γ}
{it : Iter (α := α) β} :
ForIn.forIn it init (fun c b => (fun d => .yield (g c b d)) <$> f c b) =
it.foldM (fun b c => g c b <$> f c b) init := by
ForIn.forIn (m := m) it init (fun c b => (fun d => .yield (g c b d)) <$> f c b) =
it.foldM (m := m) (fun b c => g c b <$> f c b) init := by
simp [Iter.foldM_eq_forIn]
theorem Iter.foldM_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite α Id]
{m : Type w Type w'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
theorem Iter.foldM_eq_match_step {α β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
{m : Type x Type x'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[LawfulIteratorLoop α Id m] {f : γ β m γ} {init : γ} {it : Iter (α := α) β} :
it.foldM (init := init) f = (do
match it.step with
@@ -289,20 +290,19 @@ theorem Iter.foldM_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite
generalize it.step = step
cases step using PlausibleIterStep.casesOn <;> simp [foldM_eq_forIn]
theorem Iter.foldlM_toList {α β γ : Type w} [Iterator α Id β] [Finite α Id] {m : Type w Type w'}
[Monad m] [LawfulMonad m] [IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{f : γ β m γ}
{init : γ} {it : Iter (α := α) β} :
theorem Iter.foldlM_toList {α β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
{m : Type x Type x'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[LawfulIteratorLoop α Id m] [IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{f : γ β m γ} {init : γ} {it : Iter (α := α) β} :
it.toList.foldlM (init := init) f = it.foldM (init := init) f := by
rw [Iter.foldM_eq_forIn, Iter.forIn_toList]
simp only [List.forIn_yield_eq_foldlM, id_map']
theorem IterM.forIn_eq_foldM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w Type w''} [Monad m] [LawfulMonad m]
[Finite α Id] {m : Type x Type x'} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{γ : Type x} {it : Iter (α := α) β} {init : γ}
{f : β γ m (ForInStep γ)} :
forIn it init f = ForInStep.value <$>
it.foldM (fun c b => match c with
@@ -310,31 +310,28 @@ theorem IterM.forIn_eq_foldM {α β : Type w} [Iterator α Id β]
| .done c => pure (.done c)) (ForInStep.yield init) := by
simp only [ Iter.forIn_toList, List.forIn_eq_foldlM, Iter.foldlM_toList]; rfl
theorem Iter.fold_eq_forIn {α β γ : Type w} [Iterator α Id β]
theorem Iter.fold_eq_forIn {α β : Type w} {γ : Type x} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] {f : γ β γ} {init : γ} {it : Iter (α := α) β} :
it.fold (init := init) f =
(ForIn.forIn (m := Id) it init (fun x acc => pure (ForInStep.yield (f acc x)))).run := by
rfl
theorem Iter.fold_eq_foldM {α β γ : Type w} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] {f : γ β γ} {init : γ}
{it : Iter (α := α) β} :
theorem Iter.fold_eq_foldM {α β : Type w} {γ : Type x} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] {f : γ β γ} {init : γ} {it : Iter (α := α) β} :
it.fold (init := init) f = (it.foldM (m := Id) (init := init) (pure <| f · ·)).run := by
simp [foldM_eq_forIn, fold_eq_forIn]
@[simp]
theorem Iter.forIn_pure_yield_eq_fold {α β γ : Type w} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id]
[LawfulIteratorLoop α Id Id] {f : β γ γ} {init : γ}
theorem Iter.forIn_pure_yield_eq_fold {α β : Type w} {γ : Type x} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id] {f : β γ γ} {init : γ}
{it : Iter (α := α) β} :
ForIn.forIn (m := Id) it init (fun c b => pure (.yield (f c b))) =
pure (it.fold (fun b c => f c b) init) := by
simp only [fold_eq_forIn]
rfl
theorem Iter.fold_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id]
{f : γ β γ} {init : γ} {it : Iter (α := α) β} :
theorem Iter.fold_eq_match_step {α β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id] {f : γ β γ} {init : γ} {it : Iter (α := α) β} :
it.fold (init := init) f = (match it.step with
| .yield it' out _ => it'.fold (init := f init out) f
| .skip it' _ => it'.fold (init := init) f
@@ -345,7 +342,7 @@ theorem Iter.fold_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite
cases step using PlausibleIterStep.casesOn <;> simp
@[simp]
theorem Iter.foldl_toList {α β γ : Type w} [Iterator α Id β] [Finite α Id]
theorem Iter.foldl_toList {α β : Type w} {γ : Type x} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{f : γ β γ} {init : γ} {it : Iter (α := α) β} :

View File

@@ -15,84 +15,54 @@ namespace Std.Iterators
theorem IterM.DefaultConsumers.forIn'_eq_match_step {α β : Type w} {m : Type w Type w'}
[Iterator α m β]
{n : Type w Type w''} [Monad n]
{lift : γ, m γ n γ} {γ : Type w}
{n : Type x Type x'} [Monad n]
{lift : γ δ, (γ n δ) m γ n δ} {γ : Type x}
{plausible_forInStep : β γ ForInStep γ Prop}
{wf : IteratorLoop.WellFounded α m plausible_forInStep}
{it : IterM (α := α) m β} {init : γ}
{P hP}
{f : (b : β) P b (c : γ) n (Subtype (plausible_forInStep b c))} :
IterM.DefaultConsumers.forIn' lift γ plausible_forInStep wf it init P hP f = (do
match lift _ it.step with
| .yield it' out h =>
match f out (hP _ <| .direct _, h) init with
| .yield c, _ =>
IterM.DefaultConsumers.forIn' lift _ plausible_forInStep wf it' c P
(fun _ h' => hP _ <| .indirect _, rfl, h h') f
| .done c, _ => return c
| .skip it' h =>
IterM.DefaultConsumers.forIn' lift _ plausible_forInStep wf it' init P
(fun _ h' => hP _ <| .indirect _, rfl, h h') f
| .done _ => return init) := by
{P hP} {f : (b : β) P b (c : γ) n (Subtype (plausible_forInStep b c))} :
IterM.DefaultConsumers.forIn' lift γ plausible_forInStep wf it init P hP f =
(lift _ _ · it.step) (fun
| .yield it' out h => do
match f out (hP _ <| .direct _, h) init with
| .yield c, _ =>
IterM.DefaultConsumers.forIn' lift _ plausible_forInStep wf it' c P
(fun _ h' => hP _ <| .indirect _, rfl, h h') f
| .done c, _ => return c
| .skip it' h =>
IterM.DefaultConsumers.forIn' lift _ plausible_forInStep wf it' init P
(fun _ h' => hP _ <| .indirect _, rfl, h h') f
| .done _ => return init) := by
rw [forIn']
apply bind_congr
intro step
congr; ext step
cases step using PlausibleIterStep.casesOn <;> rfl
theorem IterM.forIn'_eq {α β : Type w} {m : Type w Type w'} [Iterator α m β] [Finite α m]
{n : Type w Type w''} [Monad n] [IteratorLoop α m n] [hl : LawfulIteratorLoop α m n]
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
{n : Type w Type w''} [Monad m] [Monad n] [LawfulMonad n] [IteratorLoop α m n]
[hl : LawfulIteratorLoop α m n]
[MonadLiftT m n] [LawfulMonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
{f : (b : β) it.IsPlausibleIndirectOutput b γ n (ForInStep γ)} :
letI : ForIn' n (IterM (α := α) m β) β _ := IterM.instForIn'
ForIn'.forIn' it init f = IterM.DefaultConsumers.forIn' (fun _ => monadLift) γ (fun _ _ _ => True)
ForIn'.forIn' it init f = IterM.DefaultConsumers.forIn' (n := n)
(fun _ _ f x => monadLift x >>= f) γ (fun _ _ _ => True)
IteratorLoop.wellFounded_of_finite it init _ (fun _ => id) ((·, .intro) <$> f · · ·) := by
cases hl.lawful; rfl
simp [instForIn', ForIn'.forIn', IteratorLoop.finiteForIn',
hl.lawful (fun _ _ f x => monadLift x >>= f), IteratorLoop.defaultImplementation]
theorem IterM.forIn_eq {α β : Type w} {m : Type w Type w'} [Iterator α m β] [Finite α m]
{n : Type w Type w''} [Monad n] [IteratorLoop α m n] [hl : LawfulIteratorLoop α m n]
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
{n : Type w Type w''} [Monad m] [Monad n] [LawfulMonad n] [IteratorLoop α m n]
[hl : LawfulIteratorLoop α m n]
[MonadLiftT m n] [LawfulMonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
{f : β γ n (ForInStep γ)} :
ForIn.forIn it init f = IterM.DefaultConsumers.forIn' (fun _ => monadLift) γ (fun _ _ _ => True)
ForIn.forIn it init f = IterM.DefaultConsumers.forIn' (n := n)
(fun _ _ f x => monadLift x >>= f) γ (fun _ _ _ => True)
IteratorLoop.wellFounded_of_finite it init _ (fun _ => id) (fun out _ acc => (·, .intro) <$> f out acc) := by
cases hl.lawful; rfl
theorem IterM.DefaultConsumers.forIn'_eq_forIn' {m : Type w Type w'} {α : Type w} {β : Type w}
[Iterator α m β]
{n : Type w Type w''} [Monad n]
{lift : γ, m γ n γ} {γ : Type w}
{Pl : β γ ForInStep γ Prop}
{wf : IteratorLoop.WellFounded α m Pl}
{it : IterM (α := α) m β} {init : γ}
{P : β Prop} {hP : b, it.IsPlausibleIndirectOutput b P b}
{Q : β Prop} {hQ : b, it.IsPlausibleIndirectOutput b Q b}
{f : (b : β) P b (c : γ) n (Subtype (Pl b c))}
{g : (b : β) Q b (c : γ) n (Subtype (Pl b c))}
(hfg : b c, (hPb : P b) (hQb : Q b) f b hPb c = g b hQb c) :
IterM.DefaultConsumers.forIn' lift γ Pl wf it init P hP f =
IterM.DefaultConsumers.forIn' lift γ Pl wf it init Q hQ g := by
rw [forIn', forIn']
apply bind_congr
intro step
split
· congr
· apply hfg
· ext
split
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
assumption
· rfl
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
assumption
· rfl
termination_by IteratorLoop.WFRel.mk wf it init
decreasing_by
· exact Or.inl _, _, _
· exact Or.inr _, rfl
simp only [ForIn.forIn, forIn'_eq]
theorem IterM.forIn'_eq_match_step {α β : Type w} {m : Type w Type w'} [Iterator α m β]
[Finite α m] {n : Type w Type w''} [Monad n] [LawfulMonad n]
[Finite α m] {n : Type w Type w''} [Monad m] [Monad n] [LawfulMonad n]
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
[MonadLiftT m n] [LawfulMonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
{f : (out : β) _ γ n (ForInStep γ)} :
letI : ForIn' n (IterM (α := α) m β) β _ := IterM.instForIn'
ForIn'.forIn' it init f = (do
@@ -125,9 +95,9 @@ theorem IterM.forIn'_eq_match_step {α β : Type w} {m : Type w → Type w'} [It
· simp
theorem IterM.forIn_eq_match_step {α β : Type w} {m : Type w Type w'} [Iterator α m β]
[Finite α m] {n : Type w Type w''} [Monad n] [LawfulMonad n]
[Finite α m] {n : Type w Type w''} [Monad m] [Monad n] [LawfulMonad n]
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
[MonadLiftT m n] [LawfulMonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
{f : β γ n (ForInStep γ)} :
ForIn.forIn it init f = (do
match it.step with
@@ -138,11 +108,10 @@ theorem IterM.forIn_eq_match_step {α β : Type w} {m : Type w → Type w'} [Ite
| .skip it' _ => ForIn.forIn it' init f
| .done _ => return init) := by
simp only [forIn]
rw [forIn'_eq_match_step]
rfl
exact forIn'_eq_match_step
theorem IterM.forM_eq_forIn {α β : Type w} {m : Type w Type w'} [Iterator α m β]
[Finite α m] {n : Type w Type w''} [Monad n] [LawfulMonad n]
[Finite α m] {n : Type w Type w''} [Monad m] [Monad n] [LawfulMonad n]
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {it : IterM (α := α) m β}
{f : β n PUnit} :
@@ -150,9 +119,9 @@ theorem IterM.forM_eq_forIn {α β : Type w} {m : Type w → Type w'} [Iterator
rfl
theorem IterM.forM_eq_match_step {α β : Type w} {m : Type w Type w'} [Iterator α m β]
[Finite α m] {n : Type w Type w''} [Monad n] [LawfulMonad n]
[Finite α m] {n : Type w Type w''} [Monad m] [Monad n] [LawfulMonad n]
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {it : IterM (α := α) m β}
[MonadLiftT m n] [LawfulMonadLiftT m n] {it : IterM (α := α) m β}
{f : β n PUnit} :
ForM.forM it f = (do
match it.step with
@@ -173,7 +142,7 @@ theorem IterM.foldM_eq_forIn {α β γ : Type w} {m : Type w → Type w'} [Itera
(rfl)
theorem IterM.forIn_yield_eq_foldM {α β γ δ : Type w} {m : Type w Type w'} [Iterator α m β]
[Finite α m] {n : Type w Type w''} [Monad n] [LawfulMonad n] [IteratorLoop α m n]
[Finite α m] {n : Type w Type w''} [Monad m] [Monad n] [LawfulMonad n] [IteratorLoop α m n]
[LawfulIteratorLoop α m n] [MonadLiftT m n] {f : β γ n δ} {g : β γ δ γ} {init : γ}
{it : IterM (α := α) m β} :
ForIn.forIn it init (fun c b => (fun d => .yield (g c b d)) <$> f c b) =
@@ -181,8 +150,9 @@ theorem IterM.forIn_yield_eq_foldM {α β γ δ : Type w} {m : Type w → Type w
simp [IterM.foldM_eq_forIn]
theorem IterM.foldM_eq_match_step {α β γ : Type w} {m : Type w Type w'} [Iterator α m β] [Finite α m]
{n : Type w Type w''} [Monad n] [LawfulMonad n] [IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {f : γ β n γ} {init : γ} {it : IterM (α := α) m β} :
{n : Type w Type w''} [Monad m] [Monad n] [LawfulMonad n] [IteratorLoop α m n]
[LawfulIteratorLoop α m n] [MonadLiftT m n] [LawfulMonadLiftT m n]
{f : γ β n γ} {init : γ} {it : IterM (α := α) m β} :
it.foldM (init := init) f = (do
match it.step with
| .yield it' out _ => it'.foldM (init := f init out) f

View File

@@ -6,7 +6,8 @@ Authors: Paul Reichert
module
prelude
public import Init.Data.Iterators.Consumers
public import Init.Data.Iterators.Consumers.Collect
public import Init.Data.Iterators.Consumers.Loop
public section

View File

@@ -1369,7 +1369,7 @@ Each element of a list is related to all later elements of the list by `R`.
`Pairwise R l` means that all the elements of `l` with earlier indexes are `R`-related to all the
elements with later indexes.
For example, `Pairwise (· ≠ ·) l` asserts that `l` has no duplicates, and if `Pairwise (· < ·) l`
For example, `Pairwise (· ≠ ·) l` asserts that `l` has no duplicates, and `Pairwise (· < ·) l`
asserts that `l` is (strictly) sorted.
Examples:

View File

@@ -130,7 +130,7 @@ Safer alternatives include:
* `List.head?`, which returns an `Option`, and
* `List.headD`, which returns an explicitly-provided fallback value on empty lists.
-/
def head! [Inhabited α] : List α α
@[expose] def head! [Inhabited α] : List α α
| [] => panic! "empty list"
| a::_ => a
@@ -362,12 +362,13 @@ theorem not_lex_antisymm [DecidableEq α] {r : αα → Prop} [DecidableRel
· exact h₁ (Lex.rel hba)
· exact eq (antisymm _ _ hab hba)
protected theorem le_antisymm [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_antisymm [LT α]
[i : Std.Antisymm (¬ · < · : α α Prop)]
{as bs : List α} (h₁ : as bs) (h₂ : bs as) : as = bs :=
open Classical in
not_lex_antisymm i.antisymm h₁ h₂
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[s : Std.Antisymm (¬ · < · : α α Prop)] :
Std.Antisymm (· · : List α List α Prop) where
antisymm _ _ h₁ h₂ := List.le_antisymm h₁ h₂

View File

@@ -104,7 +104,6 @@ theorem countP_replicate {p : α → Bool} {a : α} {n : Nat} :
simp only [countP_eq_length_filter, filter_replicate]
split <;> simp
@[grind]
theorem boole_getElem_le_countP {p : α Bool} {l : List α} {i : Nat} (h : i < l.length) :
(if p l[i] then 1 else 0) l.countP p := by
induction l generalizing i with
@@ -118,6 +117,8 @@ theorem boole_getElem_le_countP {p : α → Bool} {l : List α} {i : Nat} (h : i
specialize ih h
exact le_add_right_of_le ih
grind_pattern boole_getElem_le_countP => l.countP p, l[i]
theorem Sublist.countP_le (s : l₁ <+ l₂) : countP p l₁ countP p l₂ := by
simp only [countP_eq_length_filter]
apply s.filter _ |>.length_le
@@ -142,10 +143,11 @@ grind_pattern IsInfix.countP_le => l₁ <:+: l₂, countP p l₂
-- See `Init.Data.List.Nat.Count` for `Sublist.le_countP : countP p l₂ - (l₂.length - l₁.length) ≤ countP p l₁`.
@[grind]
theorem countP_tail_le (l) : countP p l.tail countP p l :=
(tail_sublist l).countP_le
grind_pattern countP_tail_le => countP p l.tail
-- See `Init.Data.List.Nat.Count` for `le_countP_tail : countP p l - 1 ≤ countP p l.tail`.
theorem countP_filter {l : List α} :
@@ -288,12 +290,13 @@ theorem count_flatten {a : α} {l : List (List α)} : count a l.flatten = (l.map
@[simp, grind =] theorem count_reverse {a : α} {l : List α} : count a l.reverse = count a l := by
simp only [count_eq_countP, countP_eq_length_filter, filter_reverse, length_reverse]
@[grind]
theorem boole_getElem_le_count {a : α} {l : List α} {i : Nat} (h : i < l.length) :
(if l[i] == a then 1 else 0) l.count a := by
rw [count_eq_countP]
apply boole_getElem_le_countP (p := (· == a))
grind_pattern boole_getElem_le_count => l.count a, l[i]
variable [LawfulBEq α]
@[simp] theorem count_cons_self {a : α} {l : List α} : count a (a :: l) = count a l + 1 := by

View File

@@ -57,7 +57,7 @@ theorem finRange_reverse {n} : (finRange n).reverse = (finRange n).map Fin.rev :
conv => rhs; rw [finRange_succ]
rw [reverse_append, reverse_cons, reverse_nil, nil_append, singleton_append, map_reverse,
map_cons, ih, map_map, map_map]
congr; funext
congr 2; funext
simp [Fin.rev_succ]
end List

View File

@@ -523,7 +523,7 @@ private theorem findIdx?_go_eq {p : α → Bool} {xs : List α} {i : Nat} :
split
· simp_all
· simp_all only [findIdx?_go_succ, Bool.not_eq_true, Option.map_map, Nat.zero_add]
congr
congr 1
ext
simp only [Nat.add_comm i, Function.comp_apply, Nat.add_assoc]

View File

@@ -1429,12 +1429,12 @@ theorem filterMap_eq_map {f : α → β} : filterMap (some ∘ f) = map f := by
theorem filterMap_eq_map' {f : α β} : filterMap (fun x => some (f x)) = map f :=
filterMap_eq_map
@[simp] theorem filterMap_some_fun : filterMap (some : α Option α) = id := by
theorem filterMap_some_fun : filterMap (some : α Option α) = id := by
funext l
erw [filterMap_eq_map]
simp
@[grind] theorem filterMap_some {l : List α} : filterMap some l = l := by
@[simp, grind] theorem filterMap_some {l : List α} : filterMap some l = l := by
rw [filterMap_some_fun, id]
theorem map_filterMap_some_eq_filter_map_isSome {f : α Option β} {l : List α} :
@@ -2331,7 +2331,7 @@ theorem filterMap_replicate_of_some {f : α → Option β} (h : f a = some b) :
induction n with
| zero => simp
| succ n ih =>
simp only [replicate_succ, flatten_cons, ih, replicate_append_replicate,
simp only [replicate_succ, flatten_cons, ih, replicate_append_replicate,
add_one_mul, Nat.add_comm]
theorem flatMap_replicate {β} {f : α List β} : (replicate n a).flatMap f = (replicate n (f a)).flatten := by
@@ -3477,13 +3477,15 @@ theorem length_le_length_insert {l : List α} {a : α} : l.length ≤ (l.insert
grind_pattern List.length_le_length_insert => (l.insert a).length
@[grind] theorem length_insert_pos {l : List α} {a : α} : 0 < (l.insert a).length := by
theorem length_insert_pos {l : List α} {a : α} : 0 < (l.insert a).length := by
by_cases h : a l
· rw [length_insert_of_mem h]
exact length_pos_of_mem h
· rw [length_insert_of_not_mem h]
exact Nat.zero_lt_succ _
grind_pattern length_insert_pos => (l.insert a).length
theorem insert_eq {l : List α} {a : α} : l.insert a = if a l then l else a :: l := by
simp [List.insert]

View File

@@ -22,9 +22,9 @@ namespace List
@[simp] theorem not_lex_lt [LT α] {l₁ l₂ : List α} : ¬ Lex (· < ·) l₁ l₂ l₂ l₁ := Iff.rfl
protected theorem not_lt_iff_ge [LT α] {l₁ l₂ : List α} : ¬ l₁ < l₂ l₂ l₁ := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {l₁ l₂ : List α} :
protected theorem not_le_iff_gt [LT α] {l₁ l₂ : List α} :
¬ l₁ l₂ l₂ < l₁ :=
Decidable.not_not
Classical.not_not
theorem lex_irrefl {r : α α Prop} (irrefl : x, ¬r x x) (l : List α) : ¬Lex r l l := by
induction l with
@@ -78,13 +78,14 @@ theorem not_cons_lex_cons_iff [DecidableEq α] [DecidableRel r] {a b} {l₁ l₂
¬ Lex r (a :: l₁) (b :: l₂) (¬ r a b a b) (¬ r a b ¬ Lex r l₁ l₂) := by
rw [cons_lex_cons_iff, not_or, Decidable.not_and_iff_or_not, and_or_left]
theorem cons_le_cons_iff [DecidableEq α] [LT α] [DecidableLT α]
theorem cons_le_cons_iff [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
{a b} {l₁ l₂ : List α} :
(a :: l₁) (b :: l₂) a < b a = b l₁ l₂ := by
dsimp only [instLE, instLT, List.le, List.lt]
open Classical in
simp only [not_cons_lex_cons_iff, ne_eq]
constructor
· rintro (h₁, h₂ | h₁, h₂)
@@ -104,7 +105,7 @@ theorem cons_le_cons_iff [DecidableEq α] [LT α] [DecidableLT α]
· right
exact fun w => i₀.irrefl _ (h₁ w), h₂
theorem not_lt_of_cons_le_cons [DecidableEq α] [LT α] [DecidableLT α]
theorem not_lt_of_cons_le_cons [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -114,7 +115,7 @@ theorem not_lt_of_cons_le_cons [DecidableEq α] [LT α] [DecidableLT α]
· exact i₁.asymm _ _ h
· exact i₀.irrefl _
theorem le_of_cons_le_cons [DecidableEq α] [LT α] [DecidableLT α]
theorem le_of_cons_le_cons [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -165,7 +166,7 @@ instance [LT α] [Trans (· < · : αα → Prop) (· < ·) (· < ·)] :
@[deprecated List.le_antisymm (since := "2024-12-13")]
protected abbrev lt_antisymm := @List.le_antisymm
protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem lt_of_le_of_lt [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -180,7 +181,7 @@ protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
| cons c l₁ =>
apply Lex.rel
replace h₁ := not_lt_of_cons_le_cons h₁
apply Decidable.byContradiction
apply Classical.byContradiction
intro h₂
have := i₃.trans h₁ h₂
contradiction
@@ -193,9 +194,9 @@ protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
by_cases w₅ : a = c
· subst w₅
exact Lex.cons (ih (le_of_cons_le_cons h₁))
· exact Lex.rel (Decidable.byContradiction fun w₆ => w₅ (i₂.antisymm _ _ w₄ w₆))
· exact Lex.rel (Classical.byContradiction fun w₆ => w₅ (i₂.antisymm _ _ w₄ w₆))
protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_trans [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -203,7 +204,7 @@ protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
{l₁ l₂ l₃ : List α} (h₁ : l₁ l₂) (h₂ : l₂ l₃) : l₁ l₃ :=
fun h₃ => h₁ (List.lt_of_le_of_lt h₂ h₃)
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -231,9 +232,9 @@ instance [LT α] [Std.Asymm (· < · : αα → Prop)] :
Std.Asymm (· < · : List α List α Prop) where
asymm _ _ := List.lt_asymm
theorem not_lex_total [DecidableEq α] {r : α α Prop} [DecidableRel r]
theorem not_lex_total {r : α α Prop}
(h : x y : α, ¬ r x y ¬ r y x) (l₁ l₂ : List α) : ¬ Lex r l₁ l₂ ¬ Lex r l₂ l₁ := by
rw [Decidable.or_iff_not_imp_left, Decidable.not_not]
rw [Classical.or_iff_not_imp_left, Classical.not_not]
intro w₁ w₂
match l₁, l₂, w₁, w₂ with
| nil, _ :: _, .nil, w₂ => simp at w₂
@@ -246,11 +247,11 @@ theorem not_lex_total [DecidableEq α] {r : αα → Prop} [DecidableRel r]
| _ :: l₁, _ :: l₂, .cons _, .cons _ =>
obtain (_ | _) := not_lex_total h l₁ l₂ <;> contradiction
protected theorem le_total [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_total [LT α]
[i : Std.Total (¬ · < · : α α Prop)] (l₁ l₂ : List α) : l₁ l₂ l₂ l₁ :=
not_lex_total i.total l₂ l₁
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Total (¬ · < · : α α Prop)] :
Std.Total (· · : List α List α Prop) where
total := List.le_total
@@ -258,10 +259,10 @@ instance [DecidableEq α] [LT α] [DecidableLT α]
@[simp] protected theorem not_lt [LT α]
{l₁ l₂ : List α} : ¬ l₁ < l₂ l₂ l₁ := Iff.rfl
@[simp] protected theorem not_le [DecidableEq α] [LT α] [DecidableLT α]
{l₁ l₂ : List α} : ¬ l₂ l₁ l₁ < l₂ := Decidable.not_not
@[simp] protected theorem not_le [LT α]
{l₁ l₂ : List α} : ¬ l₂ l₁ l₁ < l₂ := Classical.not_not
protected theorem le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_of_lt [LT α]
[i : Std.Total (¬ · < · : α α Prop)]
{l₁ l₂ : List α} (h : l₁ < l₂) : l₁ l₂ := by
obtain (h' | h') := List.le_total l₁ l₂
@@ -269,7 +270,7 @@ protected theorem le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
· exfalso
exact h' h
protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_lt_or_eq [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
[Std.Total (¬ · < · : α α Prop)]
@@ -280,7 +281,7 @@ protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
· right
apply List.le_antisymm h h'
· left
exact Decidable.not_not.mp h'
exact Classical.not_not.mp h'
· rintro (h | rfl)
· exact List.le_of_lt h
· exact List.le_refl l₁
@@ -445,16 +446,17 @@ theorem lex_eq_false_iff_exists [BEq α] [PartialEquivBEq α] (lt : αα
simpa using w₁ (j + 1) (by simpa)
· simpa using w₂
protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {l₁ l₂ : List α} :
protected theorem lt_iff_exists [LT α] {l₁ l₂ : List α} :
l₁ < l₂
(l₁ = l₂.take l₁.length l₁.length < l₂.length)
( (i : Nat) (h₁ : i < l₁.length) (h₂ : i < l₂.length),
( j, (hj : j < i)
l₁[j]'(Nat.lt_trans hj h₁) = l₂[j]'(Nat.lt_trans hj h₂)) l₁[i] < l₂[i]) := by
open Classical in
rw [ lex_eq_true_iff_lt, lex_eq_true_iff_exists]
simp
protected theorem le_iff_exists [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_exists [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)] {l₁ l₂ : List α} :
@@ -463,6 +465,7 @@ protected theorem le_iff_exists [DecidableEq α] [LT α] [DecidableLT α]
( (i : Nat) (h₁ : i < l₁.length) (h₂ : i < l₂.length),
( j, (hj : j < i)
l₁[j]'(Nat.lt_trans hj h₁) = l₂[j]'(Nat.lt_trans hj h₂)) l₁[i] < l₂[i]) := by
open Classical in
rw [ lex_eq_false_iff_ge, lex_eq_false_iff_exists]
· simp only [isEqv_eq, beq_iff_eq, decide_eq_true_eq]
simp only [eq_comm]
@@ -477,7 +480,7 @@ theorem append_left_lt [LT α] {l₁ l₂ l₃ : List α} (h : l₂ < l₃) :
| nil => simp [h]
| cons a l₁ ih => simp [cons_lt_cons_iff, ih]
theorem append_left_le [DecidableEq α] [LT α] [DecidableLT α]
theorem append_left_le [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -511,7 +514,7 @@ protected theorem map_lt [LT α] [LT β]
| cons a l₁, cons b l₂, .rel h =>
simp [cons_lt_cons_iff, w, h]
protected theorem map_le [DecidableEq α] [LT α] [DecidableLT α] [DecidableEq β] [LT β] [DecidableLT β]
protected theorem map_le [LT α] [LT β]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]

View File

@@ -168,7 +168,7 @@ theorem max?_le_iff [Max α] [LE α]
-- This could be refactored by designing appropriate typeclasses to replace `le_refl`, `max_eq_or`,
-- and `le_min_iff`.
theorem max?_eq_some_iff [Max α] [LE α] [anti : Std.Antisymm ((· : α) ·)]
theorem max?_eq_some_iff [Max α] [LE α] [anti : Std.Antisymm (· · : α α Prop)]
(le_refl : a : α, a a)
(max_eq_or : a b : α, max a b = a max a b = b)
(max_le_iff : a b c : α, max b c a b a c a) {xs : List α} :

View File

@@ -100,7 +100,7 @@ theorem splitRevAt_eq (i : Nat) (l : List α) : splitRevAt i l = ((l.take i).rev
/--
An intermediate speed-up for `mergeSort`.
This version uses the tail-recurive `mergeTR` function as a subroutine.
This version uses the tail-recursive `mergeTR` function as a subroutine.
This is not the final version we use at runtime, as `mergeSortTR₂` is faster.
This definition is useful as an intermediate step in proving the `@[csimp]` lemma for `mergeSortTR₂`.

View File

@@ -137,7 +137,7 @@ of a number.
/--
Returns `true` if the `(n+1)`th least significant bit is `1`, or `false` if it is `0`.
-/
def testBit (m n : Nat) : Bool :=
@[expose] def testBit (m n : Nat) : Bool :=
-- `1 &&& n` is faster than `n &&& 1` for big `n`.
1 &&& (m >>> n) != 0

View File

@@ -350,12 +350,7 @@ theorem mod_le (x y : Nat) : x % y ≤ x := by
theorem mod_lt_of_lt {a b c : Nat} (h : a < c) : a % b < c :=
Nat.lt_of_le_of_lt (Nat.mod_le _ _) h
@[simp] theorem zero_mod (b : Nat) : 0 % b = 0 := by
rw [mod_eq]
have : ¬ (0 < b b = 0) := by
intro h₁, h₂
simp_all
simp [this]
@[simp] theorem zero_mod (b : Nat) : 0 % b = 0 := rfl
@[simp] theorem mod_self (n : Nat) : n % n = 0 := by
rw [mod_eq_sub_mod (Nat.le_refl _), Nat.sub_self, zero_mod]

View File

@@ -1690,17 +1690,17 @@ theorem div_lt_div_of_lt_of_dvd {a b d : Nat} (hdb : d b) (h : a < b) : a /
@[simp, grind =] theorem shiftLeft_zero : n <<< 0 = n := rfl
/-- Shiftleft on successor with multiple moved inside. -/
/-- Shift left on successor with multiple moved inside. -/
theorem shiftLeft_succ_inside (m n : Nat) : m <<< (n+1) = (2*m) <<< n := rfl
/-- Shiftleft on successor with multiple moved to outside. -/
/-- Shift left on successor with multiple moved to outside. -/
theorem shiftLeft_succ : (m n), m <<< (n + 1) = 2 * (m <<< n)
| _, 0 => rfl
| _, k + 1 => by
rw [shiftLeft_succ_inside _ (k+1)]
rw [shiftLeft_succ _ k, shiftLeft_succ_inside]
/-- Shiftright on successor with division moved inside. -/
/-- Shift right on successor with division moved inside. -/
theorem shiftRight_succ_inside : m n, m >>> (n+1) = (m/2) >>> n
| _, 0 => rfl
| _, k + 1 => by

View File

@@ -7,6 +7,7 @@ module
prelude
public import Init.Control.Basic
public import Init.Grind.Tactics
public section

View File

@@ -11,6 +11,7 @@ public import all Init.Data.Option.Instances
public import Init.Data.BEq
public import Init.Classical
public import Init.Ext
public import Init.Grind.Tactics
public section
@@ -1537,15 +1538,22 @@ theorem pfilter_guard {a : α} {p : α → Bool} {q : (a' : α) → guard p a =
/-! ### LT and LE -/
@[simp, grind] theorem not_lt_none [LT α] {a : Option α} : ¬ a < none := by cases a <;> simp [LT.lt, Option.lt]
@[grind] theorem none_lt_some [LT α] {a : α} : none < some a := by simp [LT.lt, Option.lt]
@[simp] theorem not_lt_none [LT α] {a : Option α} : ¬ a < none := by cases a <;> simp [LT.lt, Option.lt]
theorem none_lt_some [LT α] {a : α} : none < some a := by simp [LT.lt, Option.lt]
@[simp] theorem none_lt [LT α] {a : Option α} : none < a a.isSome := by cases a <;> simp [none_lt_some]
@[simp, grind] theorem some_lt_some [LT α] {a b : α} : some a < some b a < b := by simp [LT.lt, Option.lt]
@[simp] theorem some_lt_some [LT α] {a b : α} : some a < some b a < b := by simp [LT.lt, Option.lt]
@[simp, grind] theorem none_le [LE α] {a : Option α} : none a := by cases a <;> simp [LE.le, Option.le]
@[grind] theorem not_some_le_none [LE α] {a : α} : ¬ some a none := by simp [LE.le, Option.le]
@[simp] theorem none_le [LE α] {a : Option α} : none a := by cases a <;> simp [LE.le, Option.le]
theorem not_some_le_none [LE α] {a : α} : ¬ some a none := by simp [LE.le, Option.le]
@[simp] theorem le_none [LE α] {a : Option α} : a none a = none := by cases a <;> simp [not_some_le_none]
@[simp, grind] theorem some_le_some [LE α] {a b : α} : some a some b a b := by simp [LE.le, Option.le]
@[simp] theorem some_le_some [LE α] {a b : α} : some a some b a b := by simp [LE.le, Option.le]
grind_pattern not_lt_none => a < none
grind_pattern none_lt_some => none < some a
grind_pattern some_lt_some => some a < some b
grind_pattern none_le => none a
grind_pattern not_some_le_none => some a none
grind_pattern some_le_some => some a some b
@[simp]
theorem filter_le [LE α] (le_refl : x : α, x x) {o : Option α} {p : α Bool} : o.filter p o := by

View File

@@ -247,12 +247,12 @@ theorem isEq_eq_beq_eq : ∀ {o : Ordering}, o.isEq = (o == .eq) := by decide
theorem isNe_eq_not_beq_eq : {o : Ordering}, o.isNe = (!o == .eq) := by decide
theorem isNe_eq_isLT_or_isGT : {o : Ordering}, o.isNe = (o.isLT || o.isGT) := by decide
@[simp] theorem not_isLT_eq_isGE : {o : Ordering}, !o.isLT = o.isGE := by decide
@[simp] theorem not_isLE_eq_isGT : {o : Ordering}, !o.isLE = o.isGT := by decide
@[simp] theorem not_isGT_eq_isLE : {o : Ordering}, !o.isGT = o.isLE := by decide
@[simp] theorem not_isGE_eq_isLT : {o : Ordering}, !o.isGE = o.isLT := by decide
@[simp] theorem not_isNe_eq_isEq : {o : Ordering}, !o.isNe = o.isEq := by decide
theorem not_isEq_eq_isNe : {o : Ordering}, !o.isEq = o.isNe := by decide
@[simp] theorem not_isLT_eq_isGE : {o : Ordering}, (!o.isLT) = o.isGE := by decide
@[simp] theorem not_isLE_eq_isGT : {o : Ordering}, (!o.isLE) = o.isGT := by decide
@[simp] theorem not_isGT_eq_isLE : {o : Ordering}, (!o.isGT) = o.isLE := by decide
@[simp] theorem not_isGE_eq_isLT : {o : Ordering}, (!o.isGE) = o.isLT := by decide
@[simp] theorem not_isNe_eq_isEq : {o : Ordering}, (!o.isNe) = o.isEq := by decide
theorem not_isEq_eq_isNe : {o : Ordering}, (!o.isEq) = o.isNe := by decide
theorem ne_lt_iff_isGE : {o : Ordering}, ¬o = .lt o.isGE := by decide
theorem ne_gt_iff_isLE : {o : Ordering}, ¬o = .gt o.isLE := by decide

View File

@@ -8,6 +8,7 @@ module
prelude
public import Init.Data.Range.Polymorphic.Basic
public import Init.Data.Range.Polymorphic.Iterators
public import Init.Data.Range.Polymorphic.Stream
public import Init.Data.Range.Polymorphic.Lemmas
public import Init.Data.Range.Polymorphic.Nat
public import Init.Data.Range.Polymorphic.NatLemmas

View File

@@ -9,9 +9,8 @@ prelude
public import Init.Data.Range.Polymorphic.RangeIterator
public import Init.Data.Range.Polymorphic.Basic
public import Init.Data.Iterators.Combinators.Attach
public import Init.Data.Stream
public section
@[expose] public section
open Std.Iterators
@@ -26,15 +25,11 @@ def Internal.iter {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl
(r : PRange sl, su α) : Iter (α := RangeIterator su α) α :=
BoundedUpwardEnumerable.init? r.lower, r.upper
instance {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl α] :
ToStream (PRange sl, su α) (Iter (α := RangeIterator su α) α) where
toStream r := Internal.iter r
/--
Returns the elements of the given range as a list in ascending order, given that ranges of the given
type and shape support this function and the range is finite.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def toList {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl α]
[SupportsUpperBound su α]
(r : PRange sl, su α)
@@ -63,50 +58,6 @@ def size {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl α]
section Iterator
theorem RangeIterator.isPlausibleIndirectOutput_iff {su α}
[UpwardEnumerable α] [SupportsUpperBound su α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
{it : Iter (α := RangeIterator su α) α} {out : α} :
it.IsPlausibleIndirectOutput out
n, it.internalState.next.bind (UpwardEnumerable.succMany? n ·) = some out
SupportsUpperBound.IsSatisfied it.internalState.upperBound out := by
constructor
· intro h
induction h
case direct h =>
rw [RangeIterator.isPlausibleOutput_iff] at h
refine 0, by simp [h, LawfulUpwardEnumerable.succMany?_zero]
case indirect h _ ih =>
rw [RangeIterator.isPlausibleSuccessorOf_iff] at h
obtain n, hn := ih
obtain a, ha, h₁, h₂, h₃ := h
refine n + 1, ?_
simp [ha, h₃, hn.2, LawfulUpwardEnumerable.succMany?_succ_eq_succ?_bind_succMany?, h₂, hn]
· rintro n, hn, hu
induction n generalizing it
case zero =>
apply Iter.IsPlausibleIndirectOutput.direct
rw [RangeIterator.isPlausibleOutput_iff]
exact by simpa [LawfulUpwardEnumerable.succMany?_zero] using hn, hu
case succ ih =>
cases hn' : it.internalState.next
· simp [hn'] at hn
rename_i a
simp only [hn', Option.bind_some] at hn
have hle : UpwardEnumerable.LE a out := _, hn
rw [LawfulUpwardEnumerable.succMany?_succ_eq_succ?_bind_succMany?] at hn
cases hn' : UpwardEnumerable.succ? a
· simp only [hn', Option.bind_none, reduceCtorEq] at hn
rename_i a'
simp only [hn', Option.bind_some] at hn
specialize ih (it := some a', it.internalState.upperBound) hn hu
refine Iter.IsPlausibleIndirectOutput.indirect ?_ ih
rw [RangeIterator.isPlausibleSuccessorOf_iff]
refine a, _, ?_, hn', rfl
apply LawfulUpwardEnumerableUpperBound.isSatisfied_of_le _ a out
· exact hu
· exact hle
theorem Internal.isPlausibleIndirectOutput_iter_iff {sl su α}
[UpwardEnumerable α] [BoundedUpwardEnumerable sl α]
[SupportsLowerBound sl α] [SupportsUpperBound su α]
@@ -147,7 +98,6 @@ instance {sl su α m} [UpwardEnumerable α] [BoundedUpwardEnumerable sl α]
[Monad m] [Finite (RangeIterator su α) Id] :
ForIn' m (PRange sl, su α) α inferInstance where
forIn' r init f := by
haveI : MonadLift Id m := Std.Internal.idToMonad (α := _)
haveI := Iter.instForIn' (α := RangeIterator su α) (β := α) (n := m)
refine ForIn'.forIn' (α := α) (PRange.Internal.iter r) init (fun a ha acc => f a ?_ acc)
simp only [Membership.mem] at ha

View File

@@ -17,8 +17,8 @@ theorem succ_eq {n : Nat} : UpwardEnumerable.succ n = n + 1 :=
rfl
theorem ClosedOpen.toList_succ_succ {m n : Nat} :
(PRange.mk (shape := .closed, .open) (m+1) (n+1)).toList =
(PRange.mk (shape := .closed, .open) m n).toList.map (· + 1) := by
((m+1)...(n+1)).toList =
(m...n).toList.map (· + 1) := by
simp only [ succ_eq]
rw [Std.PRange.ClosedOpen.toList_succ_succ_eq_map]

View File

@@ -316,7 +316,7 @@ class LawfulClosedOpenIntersection (shape : RangeShape) (α : Type w)
[SupportsLowerBound .closed α]
[SupportsUpperBound .open α] where
/--
The intersection according to `ClosedOpenIntersection shapee α` of two ranges contains exactly
The intersection according to `ClosedOpenIntersection shape α` of two ranges contains exactly
those elements that are contained in both ranges.
-/
mem_intersection_iff {a : α} {r : PRange shape.lower, shape.upper α}

View File

@@ -110,21 +110,11 @@ theorem RangeIterator.step_eq_step {su} [UpwardEnumerable α] [SupportsUpperBoun
it.step = RangeIterator.step it, isPlausibleStep_iff.mpr rfl := by
simp [Iter.step, step_eq_monadicStep, Monadic.step_eq_step, IterM.Step.toPure]
@[always_inline, inline]
instance RepeatIterator.instIteratorLoop {su} [UpwardEnumerable α] [SupportsUpperBound su α]
{n : Type u Type w} [Monad n] :
IteratorLoop (RangeIterator su α) Id n :=
.defaultImplementation
instance RepeatIterator.instIteratorLoopPartial {su} [UpwardEnumerable α] [SupportsUpperBound su α]
{n : Type u Type w} [Monad n] : IteratorLoopPartial (RangeIterator su α) Id n :=
.defaultImplementation
instance RepeatIterator.instIteratorCollect {su} [UpwardEnumerable α] [SupportsUpperBound su α]
instance RangeIterator.instIteratorCollect {su} [UpwardEnumerable α] [SupportsUpperBound su α]
{n : Type u Type w} [Monad n] : IteratorCollect (RangeIterator su α) Id n :=
.defaultImplementation
instance RepeatIterator.instIteratorCollectPartial {su} [UpwardEnumerable α] [SupportsUpperBound su α]
instance RangeIterator.instIteratorCollectPartial {su} [UpwardEnumerable α] [SupportsUpperBound su α]
{n : Type u Type w} [Monad n] : IteratorCollectPartial (RangeIterator su α) Id n :=
.defaultImplementation
@@ -370,4 +360,223 @@ instance RangeIterator.instLawfulDeterministicIterator {su} [UpwardEnumerable α
LawfulDeterministicIterator (RangeIterator su α) Id where
isPlausibleStep_eq_eq it := Monadic.step it, rfl
end Std.PRange
theorem RangeIterator.Monadic.isPlausibleIndirectOutput_iff {su α}
[UpwardEnumerable α] [SupportsUpperBound su α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
{it : IterM (α := RangeIterator su α) Id α} {out : α} :
it.IsPlausibleIndirectOutput out
n, it.internalState.next.bind (UpwardEnumerable.succMany? n ·) = some out
SupportsUpperBound.IsSatisfied it.internalState.upperBound out := by
constructor
· intro h
induction h
case direct h =>
rw [RangeIterator.Monadic.isPlausibleOutput_iff] at h
refine 0, by simp [h, LawfulUpwardEnumerable.succMany?_zero]
case indirect h _ ih =>
rw [RangeIterator.Monadic.isPlausibleSuccessorOf_iff] at h
obtain n, hn := ih
obtain a, ha, h₁, h₂, h₃ := h
refine n + 1, ?_
simp [ha, h₃, hn.2, LawfulUpwardEnumerable.succMany?_succ_eq_succ?_bind_succMany?, h₂, hn]
· rintro n, hn, hu
induction n generalizing it
case zero =>
apply IterM.IsPlausibleIndirectOutput.direct
rw [RangeIterator.Monadic.isPlausibleOutput_iff]
exact by simpa [LawfulUpwardEnumerable.succMany?_zero] using hn, hu
case succ ih =>
cases hn' : it.internalState.next
· simp [hn'] at hn
rename_i a
simp only [hn', Option.bind_some] at hn
have hle : UpwardEnumerable.LE a out := _, hn
rw [LawfulUpwardEnumerable.succMany?_succ_eq_succ?_bind_succMany?] at hn
cases hn' : UpwardEnumerable.succ? a
· simp only [hn', Option.bind_none, reduceCtorEq] at hn
rename_i a'
simp only [hn', Option.bind_some] at hn
specialize ih (it := some a', it.internalState.upperBound) hn hu
refine IterM.IsPlausibleIndirectOutput.indirect ?_ ih
rw [RangeIterator.Monadic.isPlausibleSuccessorOf_iff]
refine a, _, ?_, hn', rfl
apply LawfulUpwardEnumerableUpperBound.isSatisfied_of_le _ a out
· exact hu
· exact hle
theorem RangeIterator.isPlausibleIndirectOutput_iff {su α}
[UpwardEnumerable α] [SupportsUpperBound su α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
{it : Iter (α := RangeIterator su α) α} {out : α} :
it.IsPlausibleIndirectOutput out
n, it.internalState.next.bind (UpwardEnumerable.succMany? n ·) = some out
SupportsUpperBound.IsSatisfied it.internalState.upperBound out := by
simp only [Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM,
Monadic.isPlausibleIndirectOutput_iff, Iter.toIterM]
section IteratorLoop
/-!
## Efficient `IteratorLoop` instance
As long as the compiler cannot optimize away the `Option` in the internal state, we use a special
loop implementation.
-/
@[always_inline, inline]
instance RangeIterator.instIteratorLoop {su} [UpwardEnumerable α] [SupportsUpperBound su α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
{n : Type u Type w} [Monad n] :
IteratorLoop (RangeIterator su α) Id n where
forIn _ γ Pl wf it init f :=
match it with
| some next, upperBound =>
if hu : SupportsUpperBound.IsSatisfied upperBound next then
loop γ Pl wf upperBound next init (fun a ha₁ ha₂ c => f a ?hf c) next ?hle hu
else
return init
| none, _ => return init
where
@[specialize]
loop γ Pl wf (upperBound : Bound su α) least acc
(f : (out : α) UpwardEnumerable.LE least out SupportsUpperBound.IsSatisfied upperBound out (c : γ) n (Subtype (fun s : ForInStep γ => Pl out c s)))
(next : α) (hl : UpwardEnumerable.LE least next) (hu : SupportsUpperBound.IsSatisfied upperBound next) : n γ := do
match f next hl hu acc with
| .yield acc', h =>
match hs : UpwardEnumerable.succ? next with
| some next' =>
if hu : SupportsUpperBound.IsSatisfied upperBound next' then
loop γ Pl wf upperBound least acc' f next' ?hle' hu
else
return acc'
| none => return acc'
| .done acc', _ => return acc'
termination_by IteratorLoop.WithWF.mk some next, upperBound acc (hwf := wf)
decreasing_by
simp [IteratorLoop.rel, RangeIterator.Monadic.isPlausibleStep_iff,
RangeIterator.Monadic.step, *]
finally
case hf =>
rw [RangeIterator.Monadic.isPlausibleIndirectOutput_iff]
obtain n, hn := ha₁
exact n, hn, ha₂
case hle =>
exact UpwardEnumerable.le_refl _
case hle' =>
refine UpwardEnumerable.le_trans hl 1, ?_
simp [UpwardEnumerable.succMany?_one, hs]
partial instance RepeatIterator.instIteratorLoopPartial {su} [UpwardEnumerable α]
[SupportsUpperBound su α] [LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
{n : Type u Type w} [Monad n] : IteratorLoopPartial (RangeIterator su α) Id n where
forInPartial _ γ it init f :=
match it with
| some next, upperBound =>
if hu : SupportsUpperBound.IsSatisfied upperBound next then
loop γ upperBound next init (fun a ha₁ ha₂ c => f a ?hf c) next ?hle hu
else
return init
| none, _ => return init
where
@[specialize]
loop γ (upperBound : Bound su α) least acc
(f : (out : α) UpwardEnumerable.LE least out SupportsUpperBound.IsSatisfied upperBound out (c : γ) n (ForInStep γ))
(next : α) (hl : UpwardEnumerable.LE least next) (hu : SupportsUpperBound.IsSatisfied upperBound next) : n γ := do
match f next hl hu acc with
| .yield acc' =>
match hs : UpwardEnumerable.succ? next with
| some next' =>
if hu : SupportsUpperBound.IsSatisfied upperBound next' then
loop γ upperBound least acc' f next' ?hle' hu
else
return acc'
| none => return acc'
| .done acc' => return acc'
finally
case hf =>
rw [RangeIterator.Monadic.isPlausibleIndirectOutput_iff]
obtain n, hn := ha₁
exact n, hn, ha₂
case hle =>
exact UpwardEnumerable.le_refl _
case hle' =>
refine UpwardEnumerable.le_trans hl 1, ?_
simp [UpwardEnumerable.succMany?_one, hs]
theorem RangeIterator.instIteratorLoop.loop_eq {su} [UpwardEnumerable α] [SupportsUpperBound su α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
{n : Type u Type w} [Monad n] [LawfulMonad n] {γ : Type u}
{lift} [Internal.LawfulMonadLiftBindFunction lift]
{PlausibleForInStep} {upperBound} {next} {hl} {hu} {f} {acc} {wf} :
loop (α := α) (su := su) (n := n) γ PlausibleForInStep wf upperBound least acc f next hl hu =
(do
match f next hl hu acc with
| .yield c, _ =>
letI it' : IterM (α := RangeIterator su α) Id α := UpwardEnumerable.succ? next, upperBound
IterM.DefaultConsumers.forIn' (m := Id) lift γ
PlausibleForInStep wf it' c it'.IsPlausibleIndirectOutput (fun _ => id)
(fun b h c => f b
(by
refine UpwardEnumerable.le_trans hl ?_
simp only [RangeIterator.Monadic.isPlausibleIndirectOutput_iff, it',
LawfulUpwardEnumerable.succMany?_succ_eq_succ?_bind_succMany?] at h
exact h.choose + 1, h.choose_spec.1)
(by simp only [RangeIterator.Monadic.isPlausibleIndirectOutput_iff, it'] at h; exact h.choose_spec.2) c)
| .done c, _ => return c) := by
rw [loop]
apply bind_congr
intro step
split
· split
· split
· simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp only [Monadic.step_eq_step, Monadic.step, reduceIte, *,
Internal.LawfulMonadLiftBindFunction.liftBind_pure]
rw [loop_eq (lift := lift)]
apply bind_congr
intro step
split
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
intros; rfl
· simp
· simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp [Monadic.step_eq_step, Monadic.step, *,
Internal.LawfulMonadLiftBindFunction.liftBind_pure]
· simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp [Monadic.step_eq_step, Monadic.step, Internal.LawfulMonadLiftBindFunction.liftBind_pure]
· simp
termination_by IteratorLoop.WithWF.mk some next, upperBound acc (hwf := wf)
decreasing_by
simp [IteratorLoop.rel, RangeIterator.Monadic.isPlausibleStep_iff,
RangeIterator.Monadic.step, *]
instance RangeIterator.instLawfulIteratorLoop {su} [UpwardEnumerable α] [SupportsUpperBound su α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
{n : Type u Type w} [Monad n] [LawfulMonad n] :
LawfulIteratorLoop (RangeIterator su α) Id n where
lawful := by
intro lift instLawfulMonadLiftFunction
ext γ PlausibleForInStep hwf it init f
simp only [IteratorLoop.forIn, IteratorLoop.defaultImplementation]
rw [IterM.DefaultConsumers.forIn']
simp only [RangeIterator.Monadic.step_eq_step, RangeIterator.Monadic.step]
simp only [Internal.LawfulMonadLiftBindFunction.liftBind_pure]
split
· rename_i it f next upperBound f'
simp
split
· simp only
rw [instIteratorLoop.loop_eq (lift := lift)]
apply bind_congr
intro step
split
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
intro b c hPb hQb
congr
· simp
· simp
· simp
end Std.PRange.IteratorLoop

View File

@@ -0,0 +1,22 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
public import Init.Data.Range.Polymorphic.Iterators
public import Init.Data.Stream
public section
open Std.Iterators
namespace Std.PRange
instance {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl α] :
ToStream (PRange sl, su α) (Iter (α := RangeIterator su α) α) where
toStream r := Internal.iter r
end Std.PRange

View File

@@ -87,7 +87,7 @@ class LawfulUpwardEnumerable (α : Type u) [UpwardEnumerable α] where
succMany?_zero (a : α) : UpwardEnumerable.succMany? 0 a = some a
/--
The `n + 1`-th successor of `a` is the successor of the `n`-th successor, given that said
successors actualy exist.
successors actually exist.
-/
succMany?_succ (n : Nat) (a : α) :
UpwardEnumerable.succMany? (n + 1) a = (UpwardEnumerable.succMany? n a).bind UpwardEnumerable.succ?

View File

@@ -8,8 +8,11 @@ module
prelude
public import Init.Core
public import Init.Data.Slice.Array.Basic
public import Init.Data.Iterators.Combinators.Attach
public import Init.Data.Iterators.Combinators.FilterMap
import Init.Data.Iterators.Combinators.Attach
import Init.Data.Iterators.Combinators.FilterMap
import Init.Data.Iterators.Combinators.ULift
public import Init.Data.Iterators.Consumers.Collect
public import Init.Data.Iterators.Consumers.Loop
public import all Init.Data.Range.Polymorphic.Basic
public import Init.Data.Range.Polymorphic.Nat
public import Init.Data.Range.Polymorphic.Iterators
@@ -26,6 +29,7 @@ open Std Slice PRange Iterators
variable {shape : RangeShape} {α : Type u}
@[no_expose]
instance {s : Subarray α} : ToIterator s Id α :=
.of _
(PRange.Internal.iter (s.internalRepresentation.start...<s.internalRepresentation.stop)
@@ -39,3 +43,102 @@ where finally
intro out _ h
have := s.internalRepresentation.stop_le_array_size
omega
universe v w
@[no_expose] instance {s : Subarray α} : Iterator (ToIterator.State s Id) Id α := inferInstance
@[no_expose] instance {s : Subarray α} : Finite (ToIterator.State s Id) Id := inferInstance
@[no_expose] instance {s : Subarray α} : IteratorCollect (ToIterator.State s Id) Id Id := inferInstance
@[no_expose] instance {s : Subarray α} : IteratorCollectPartial (ToIterator.State s Id) Id Id := inferInstance
@[no_expose] instance {s : Subarray α} {m : Type v Type w} [Monad m] :
IteratorLoop (ToIterator.State s Id) Id m := inferInstance
@[no_expose] instance {s : Subarray α} {m : Type v Type w} [Monad m] :
IteratorLoopPartial (ToIterator.State s Id) Id m := inferInstance
@[no_expose] instance {s : Subarray α} :
IteratorSize (ToIterator.State s Id) Id := inferInstance
@[no_expose] instance {s : Subarray α} :
IteratorSizePartial (ToIterator.State s Id) Id := inferInstance
@[no_expose]
instance {α : Type u} {m : Type v Type w} :
ForIn m (Subarray α) α where
forIn xs init f := forIn (Std.Slice.Internal.iter xs) init f
/-!
Without defining the following function `Subarray.foldlM`, it is still possible to call
`subarray.foldlM`, which would be elaborated to `Slice.foldlM (s := subarray)`. However, in order to
maximize backward compatibility and avoid confusion in the manual entry for `Subarray`, we
explicitly provide the wrapper function `Subarray.foldlM` for `Slice.foldlM`, providing a more
specific docstring.
-/
/--
Folds a monadic operation from left to right over the elements in a subarray.
An accumulator of type `β` is constructed by starting with `init` and monadically combining each
element of the subarray with the current accumulator value in turn. The monad in question may permit
early termination or repetition.
Examples:
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := "") fun acc x => do
let l ← Option.guard (· ≠ 0) x.length
return s!"{acc}({l}){x} "
```
```output
some "(3)red (5)green (4)blue "
```
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := 0) fun acc x => do
let l ← Option.guard (· ≠ 5) x.length
return s!"{acc}({l}){x} "
```
```output
none
```
-/
@[inline]
def Subarray.foldlM {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (f : β α m β) (init : β) (as : Subarray α) : m β :=
Slice.foldlM f (init := init) as
/--
Folds an operation from left to right over the elements in a subarray.
An accumulator of type `β` is constructed by starting with `init` and combining each
element of the subarray with the current accumulator value in turn.
Examples:
* `#["red", "green", "blue"].toSubarray.foldl (· + ·.length) 0 = 12`
* `#["red", "green", "blue"].toSubarray.popFront.foldl (· + ·.length) 0 = 9`
-/
@[inline]
def foldl {α : Type u} {β : Type v} (f : β α β) (init : β) (as : Subarray α) : β :=
Slice.foldl f (init := init) as
namespace Array
/--
Allocates a new array that contains the contents of the subarray.
-/
@[coe]
def ofSubarray (s : Subarray α) : Array α :=
Slice.toArray s
instance : Coe (Subarray α) (Array α) := ofSubarray
instance : Append (Subarray α) where
append x y :=
let a := x.toArray ++ y.toArray
a.toSubarray 0 a.size
/-- `Subarray` representation. -/
protected def Subarray.repr [Repr α] (s : Subarray α) : Std.Format :=
repr s.toArray ++ ".toSubarray"
instance [Repr α] : Repr (Subarray α) where
reprPrec s _ := Subarray.repr s
instance [ToString α] : ToString (Subarray α) where
toString s := toString s.toArray
end Array
@[inherit_doc Array.ofSubarray]
def Subarray.toArray (s : Subarray α) : Array α :=
Array.ofSubarray s

View File

@@ -21,7 +21,7 @@ open Std.Iterators Std.PRange
namespace Std.Slice.Array
theorem internalIter_eq {α : Type u} {s : Subarray α} :
private theorem internalIter_eq {α : Type u} {s : Subarray α} :
Internal.iter s = (PRange.Internal.iter (s.start...<s.stop)
|>.attachWith (· < s.array.size)
(fun out h => h
@@ -32,7 +32,7 @@ theorem internalIter_eq {α : Type u} {s : Subarray α} :
|>.map fun | .up i => s.array[i.1]) := by
simp [Internal.iter, ToIterator.iter_eq, Subarray.start, Subarray.stop, Subarray.array]
theorem toList_internalIter {α : Type u} {s : Subarray α} :
private theorem toList_internalIter {α : Type u} {s : Subarray α} :
(Internal.iter s).toList =
((s.start...s.stop).toList
|>.attachWith (· < s.array.size)

View File

@@ -7,6 +7,7 @@ module
prelude
public import all Init.Data.Slice.Operations
import Init.Data.Iterators.Lemmas.Consumers
public section

View File

@@ -8,7 +8,7 @@ module
prelude
public import Init.Data.Slice.Basic
public import Init.Data.Slice.Notation
public import Init.Data.Iterators
public import Init.Data.Iterators.ToIterator
public section
@@ -34,26 +34,72 @@ Returns the number of elements with distinct indices in the given slice.
Example: `#[1, 1, 1][0...2].size = 2`.
-/
@[always_inline, inline]
def size (s : Slice g) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
def size (s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[IteratorSize (ToIterator.State s Id) Id] :=
Internal.iter s |>.size
/-- Allocates a new array that contains the elements of the slice. -/
@[always_inline, inline]
def toArray (s : Slice g) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
def toArray (s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[IteratorCollect (ToIterator.State s Id) Id Id] [Finite (ToIterator.State s Id) Id] : Array β :=
Internal.iter s |>.toArray
/-- Allocates a new list that contains the elements of the slice. -/
@[always_inline, inline]
def toList (s : Slice g) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
def toList (s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[IteratorCollect (ToIterator.State s Id) Id Id] [Finite (ToIterator.State s Id) Id] : List β :=
Internal.iter s |>.toList
/-- Allocates a new list that contains the elements of the slice in reverse order. -/
@[always_inline, inline]
def toListRev (s : Slice g) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
def toListRev (s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[Finite (ToIterator.State s Id) Id] : List β :=
Internal.iter s |>.toListRev
/--
Folds a monadic operation from left to right over the elements in a slice.
An accumulator of type `β` is constructed by starting with `init` and monadically combining each
element of the slice with the current accumulator value in turn. The monad in question may permit
early termination or repetition.
Examples for the special case of subarrays:
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := "") fun acc x => do
let l ← Option.guard (· ≠ 0) x.length
return s!"{acc}({l}){x} "
```
```output
some "(3)red (5)green (4)blue "
```
```lean example
#eval #["red", "green", "blue"].toSubarray.foldlM (init := 0) fun acc x => do
let l ← Option.guard (· ≠ 5) x.length
return s!"{acc}({l}){x} "
```
```output
none
```
-/
@[always_inline, inline]
def foldlM {γ : Type u} {β : Type v}
{δ : Type w} {m : Type w Type w'} [Monad m] (f : δ β m δ) (init : δ)
(s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[IteratorLoop (ToIterator.State s Id) Id m] [Finite (ToIterator.State s Id) Id] : m δ :=
Internal.iter s |>.foldM f init
/--
Folds an operation from left to right over the elements in a slice.
An accumulator of type `β` is constructed by starting with `init` and combining each
element of the slice with the current accumulator value in turn.
Examples for the special case of subarrays:
* `#["red", "green", "blue"].toSubarray.foldl (· + ·.length) 0 = 12`
* `#["red", "green", "blue"].toSubarray.popFront.foldl (· + ·.length) 0 = 9`
-/
@[always_inline, inline]
def foldl {γ : Type u} {β : Type v}
{δ : Type w} (f : δ β δ) (init : δ)
(s : Slice γ) [ToIterator s Id β] [Iterator (ToIterator.State s Id) Id β]
[IteratorLoop (ToIterator.State s Id) Id Id] [Finite (ToIterator.State s Id) Id] : δ :=
Internal.iter s |>.fold f init
end Std.Slice

View File

@@ -220,22 +220,22 @@ If both the replacement character and the replaced character are 7-bit ASCII cha
string is not shared, then it is updated in-place and not copied.
Examples:
* `abc.modify ⟨1⟩ Char.toUpper = "aBc"`
* `abc.modify ⟨3⟩ Char.toUpper = "abc"`
* `"abc".modify ⟨1⟩ Char.toUpper = "aBc"`
* `"abc".modify ⟨3⟩ Char.toUpper = "abc"`
-/
def modify (s : String) (i : Pos) (f : Char Char) : String :=
s.set i <| f <| s.get i
/--
Returns the next position in a string after position `p`. The result is unspecified if `p` is not a
valid position or if `p = s.endPos`.
Returns the next position in a string after position `p`. If `p` is not a valid position or
`p = s.endPos`, returns the position one byte after `p`.
A run-time bounds check is performed to determine whether `p` is at the end of the string. If a
bounds check has already been performed, use `String.next'` to avoid a repeated check.
Some examples where the result is unspecified:
* `"abc".next ⟨3⟩`, since `3 = "abc".endPos`
* `"L∃∀N".next ⟨2⟩`, since `2` points into the middle of a multi-byte UTF-8 character
Some examples of edge cases:
* `"abc".next ⟨3⟩ = ⟨4⟩`, since `3 = "abc".endPos`
* `"L∃∀N".next ⟨2⟩ = ⟨3⟩`, since `2` points into the middle of a multi-byte UTF-8 character
Examples:
* `"abc".get ("abc".next 0) = 'b'`
@@ -247,17 +247,18 @@ def next (s : @& String) (p : @& Pos) : Pos :=
p + c
def utf8PrevAux : List Char Pos Pos Pos
| [], _, _ => 0
| [], _, p => p.byteIdx - 1
| c::cs, i, p =>
let i' := i + c
if i' = p then i else utf8PrevAux cs i' p
if p i' then i else utf8PrevAux cs i' p
/--
Returns the position in a string before a specified position, `p`. If `p = ⟨0⟩`, returns `0`. If `p`
is not a valid position, the result is unspecified.
is greater than `endPos`, returns the position one byte before `p`. Otherwise, if `p` occurs in the
middle of a multi-byte character, returns the beginning position of that character.
For example, `"L∃∀N".prev ⟨3⟩` is unspecified, since byte 3 occurs in the middle of the multi-byte
character `'∃'`.
For example, `"L∃∀N".prev ⟨3⟩` is `⟨1⟩`, since byte 3 occurs in the middle of the multi-byte
character `'∃'` that starts at byte 1.
Examples:
* `"abc".get ("abc".endPos |> "abc".prev) = 'c'`
@@ -265,7 +266,7 @@ Examples:
-/
@[extern "lean_string_utf8_prev", expose]
def prev : (@& String) (@& Pos) Pos
| s, p => if p = 0 then 0 else utf8PrevAux s 0 p
| s, p => utf8PrevAux s 0 p
/--
Returns the first character in `s`. If `s = ""`, returns `(default : Char)`.
@@ -339,7 +340,7 @@ Requires evidence, `h`, that `p` is within bounds. No run-time bounds check is p
A typical pattern combines `String.next'` with a dependent `if`-expression to avoid the overhead of
an additional bounds check. For example:
```
def next? (s: String) (p : String.Pos) : Option Char :=
def next? (s : String) (p : String.Pos) : Option Char :=
if h : s.atEnd p then none else s.get (s.next' p h)
```
@@ -369,20 +370,17 @@ protected theorem Pos.ne_zero_of_lt : {a b : Pos} → a < b → b ≠ 0
theorem lt_next (s : String) (i : Pos) : i.1 < (s.next i).1 :=
Nat.add_lt_add_left (Char.utf8Size_pos _) _
theorem utf8PrevAux_lt_of_pos : (cs : List Char) (i p : Pos), p 0
theorem utf8PrevAux_lt_of_pos : (cs : List Char) (i p : Pos), i < p p 0
(utf8PrevAux cs i p).1 < p.1
| [], _, _, h =>
Nat.lt_of_le_of_lt (Nat.zero_le _)
(Nat.zero_lt_of_ne_zero (mt (congrArg Pos.mk) h))
| c::cs, i, p, h => by
| [], _, _, _, h => Nat.sub_one_lt (mt (congrArg Pos.mk) h)
| c::cs, i, p, h, h' => by
simp [utf8PrevAux]
apply iteInduction (motive := (Pos.byteIdx · < _)) <;> intro h'
next => exact h' Nat.add_lt_add_left (Char.utf8Size_pos _) _
next => exact utf8PrevAux_lt_of_pos _ _ _ h
apply iteInduction (motive := (Pos.byteIdx · < _)) <;> intro h''
next => exact h
next => exact utf8PrevAux_lt_of_pos _ _ _ (Nat.lt_of_not_le h'') h'
theorem prev_lt_of_pos (s : String) (i : Pos) (h : i 0) : (s.prev i).1 < i.1 := by
simp [prev, h]
exact utf8PrevAux_lt_of_pos _ _ _ h
theorem prev_lt_of_pos (s : String) (i : Pos) (h : i 0) : (s.prev i).1 < i.1 :=
utf8PrevAux_lt_of_pos _ _ _ (Nat.zero_lt_of_ne_zero (mt (congrArg Pos.mk) h)) h
def posOfAux (s : String) (c : Char) (stopPos : Pos) (pos : Pos) : Pos :=
if h : pos < stopPos then
@@ -419,7 +417,7 @@ Returns the position of the last occurrence of a character, `c`, in a string `s`
contain `c`, returns `none`.
Examples:
* `"abcabc".refPosOf 'a' = some ⟨3⟩`
* `"abcabc".revPosOf 'a' = some ⟨3⟩`
* `"abcabc".revPosOf 'z' = none`
* `"L∃∀N".revPosOf '∀' = some ⟨4⟩`
-/
@@ -2068,7 +2066,11 @@ end Pos
theorem lt_next' (s : String) (p : Pos) : p < next s p := lt_next ..
@[simp] theorem prev_zero (s : String) : prev s 0 = 0 := rfl
@[simp] theorem prev_zero (s : String) : prev s 0 = 0 := by
cases s with | mk cs
cases cs
next => rfl
next => simp [prev, utf8PrevAux, Pos.le_iff]
@[simp] theorem get'_eq (s : String) (p : Pos) (h) : get' s p h = get s p := rfl

View File

@@ -9,7 +9,7 @@ prelude
public import Init.Data.UInt.BasicAux
public import Init.Data.BitVec.Basic
public section
@[expose] public section
set_option linter.missingDocs true

View File

@@ -8,13 +8,14 @@ module
prelude
public meta import Init.Coe
public import Init.Data.Stream
public import Init.Data.Array.Lemmas
public import Init.Data.Array.MapIdx
public import Init.Data.Array.InsertIdx
public import Init.Data.Array.Range
public import Init.Data.Range
import Init.Data.Slice.Array.Basic
public import Init.Data.Stream
-- TODO: Making this private leads to a panic in Init.Grind.Ring.Poly.
public import Init.Data.Slice.Array.Iterator
public section
@@ -54,6 +55,11 @@ open Lean in
macro_rules
| `(#v[ $elems,* ]) => `(Vector.mk (n := $(quote elems.getElems.size)) #[$elems,*] rfl)
@[app_unexpander Vector.mk]
meta def unexpandMk : Lean.PrettyPrinter.Unexpander
| `($_ #[ $elems,* ] $_) => `(#v[ $elems,* ])
| _ => throw ()
recommended_spelling "empty" for "#v[]" in [Vector.mk, «term#v[_,]»]
recommended_spelling "singleton" for "#v[x]" in [Vector.mk, «term#v[_,]»]
@@ -562,7 +568,7 @@ Lexicographic comparator for vectors.
- there is an index `i` such that `lt v[i] w[i]`, and for all `j < i`, `v[j] == w[j]`.
-/
def lex [BEq α] (xs ys : Vector α n) (lt : α α Bool := by exact (· < ·)) : Bool := Id.run do
for h : i in [0 : n] do
for h : i in 0...n do
if lt xs[i] ys[i] then
return true
else if xs[i] != ys[i] then

View File

@@ -55,11 +55,12 @@ theorem getElem_eraseIdx {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} (h'
rw [ getElem?_eq_getElem, getElem?_eraseIdx]
split <;> simp
@[grind ]
theorem mem_of_mem_eraseIdx {xs : Vector α n} {i : Nat} {h} {a : α} (h : a xs.eraseIdx i) : a xs := by
rcases xs with xs, rfl
simpa using Array.mem_of_mem_eraseIdx (by simpa using h)
grind_pattern mem_of_mem_eraseIdx => a xs.eraseIdx i
theorem eraseIdx_append_of_lt_size {xs : Vector α n} {k : Nat} (hk : k < n) (xs' : Vector α n) (h) :
eraseIdx (xs ++ xs') k = (eraseIdx xs k ++ xs').cast (by omega) := by
rcases xs with xs

View File

@@ -284,7 +284,7 @@ set_option linter.indexVariables false in
(xs.drop i).toArray = xs.toArray.extract i n := by
simp [drop]
@[simp, grind] theorem toArray_empty : (#v[] : Vector α 0).toArray = #[] := rfl
@[simp, grind =] theorem toArray_empty : (#v[] : Vector α 0).toArray = #[] := rfl
@[simp, grind] theorem toArray_emptyWithCapacity {cap} :
(Vector.emptyWithCapacity (α := α) cap).toArray = Array.emptyWithCapacity cap := rfl
@@ -828,7 +828,7 @@ theorem getElem?_eq_none {xs : Vector α n} (h : n ≤ i) : xs[i]? = none := by
-- This is a more aggressive pattern than for `List/Array.getElem?_eq_none`, because
-- `length/size` won't appear.
grind_pattern Vector.getElem?_eq_none => n i, xs[i]?
grind_pattern Vector.getElem?_eq_none => xs[i]?
@[simp] theorem getElem?_eq_getElem {xs : Vector α n} {i : Nat} (h : i < n) : xs[i]? = some xs[i] :=
getElem?_pos ..
@@ -1213,18 +1213,18 @@ theorem contains_iff [BEq α] [LawfulBEq α] {a : α} {as : Vector α n} :
instance [BEq α] [LawfulBEq α] (a : α) (as : Vector α n) : Decidable (a as) :=
decidable_of_decidable_of_iff contains_iff
@[grind] theorem contains_empty [BEq α] : (#v[] : Vector α 0).contains a = false := rfl
@[grind] theorem contains_empty [BEq α] : (#v[] : Vector α 0).contains a = false := by simp
@[simp, grind] theorem contains_eq_mem [BEq α] [LawfulBEq α] {a : α} {as : Vector α n} :
as.contains a = decide (a as) := by
rw [Bool.eq_iff_iff, contains_iff, decide_eq_true_iff]
@[simp] theorem any_push [BEq α] {as : Vector α n} {a : α} {p : α Bool} :
@[simp] theorem any_push {as : Vector α n} {a : α} {p : α Bool} :
(as.push a).any p = (as.any p || p a) := by
rcases as with as, rfl
simp
@[simp] theorem all_push [BEq α] {as : Vector α n} {a : α} {p : α Bool} :
@[simp] theorem all_push {as : Vector α n} {a : α} {p : α Bool} :
(as.push a).all p = (as.all p && p a) := by
rcases as with as, rfl
simp
@@ -1287,11 +1287,12 @@ theorem mem_set {xs : Vector α n} {i : Nat} {a : α} (hi : i < n) : a ∈ xs.se
simp [mem_iff_getElem]
exact i, (by simpa using hi), by simp
@[grind ]
theorem mem_or_eq_of_mem_set {xs : Vector α n} {i : Nat} {a b : α} {hi : i < n} (h : a xs.set i b) : a xs a = b := by
cases xs
simpa using Array.mem_or_eq_of_mem_set (by simpa using h)
grind_pattern mem_or_eq_of_mem_set => a xs.set i b
/-! ### setIfInBounds -/
@[simp, grind] theorem setIfInBounds_empty {i : Nat} {a : α} :
@@ -2975,7 +2976,7 @@ variable [BEq α]
rcases xs with xs, rfl
simp
@[simp, grind] theorem replace_empty : (#v[] : Vector α 0).replace a b = #v[] := by rfl
@[simp, grind] theorem replace_empty : (#v[] : Vector α 0).replace a b = #v[] := by simp
@[grind] theorem replace_singleton {a b c : α} : #v[a].replace b c = #v[if a == b then c else a] := by
simp

View File

@@ -10,6 +10,7 @@ public import all Init.Data.Vector.Basic
public import Init.Data.Vector.Lemmas
public import all Init.Data.Array.Lex.Basic
public import Init.Data.Array.Lex.Lemmas
import Init.Data.Range.Polymorphic.Lemmas
public section
@@ -21,16 +22,19 @@ namespace Vector
/-! ### Lexicographic ordering -/
@[simp, grind =] theorem lt_toArray [LT α] {xs ys : Vector α n} : xs.toArray < ys.toArray xs < ys := Iff.rfl
@[simp, grind =] theorem le_toArray [LT α] {xs ys : Vector α n} : xs.toArray ys.toArray xs ys := Iff.rfl
@[simp] theorem lt_toArray [LT α] {xs ys : Vector α n} : xs.toArray < ys.toArray xs < ys := Iff.rfl
@[simp] theorem le_toArray [LT α] {xs ys : Vector α n} : xs.toArray ys.toArray xs ys := Iff.rfl
grind_pattern lt_toArray => xs.toArray < ys.toArray
grind_pattern le_toArray => xs.toArray ys.toArray
@[simp] theorem lt_toList [LT α] {xs ys : Vector α n} : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp] theorem le_toList [LT α] {xs ys : Vector α n} : xs.toList ys.toList xs ys := Iff.rfl
protected theorem not_lt_iff_ge [LT α] {xs ys : Vector α n} : ¬ xs < ys ys xs := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Vector α n} :
protected theorem not_le_iff_gt [LT α] {xs ys : Vector α n} :
¬ xs ys ys < xs :=
Decidable.not_not
Classical.not_not
@[simp] theorem mk_lt_mk [LT α] :
Vector.mk (α := α) (n := n) data₁ size₁ < Vector.mk data₂ size₂ data₁ < data₂ := Iff.rfl
@@ -40,7 +44,7 @@ protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys
@[simp] theorem mk_lex_mk [BEq α] {lt : α α Bool} {xs ys : Array α} {n₁ : xs.size = n} {n₂ : ys.size = n} :
(Vector.mk xs n₁).lex (Vector.mk ys n₂) lt = xs.lex ys lt := by
simp [Vector.lex, Array.lex, n₁, n₂]
simp [Vector.lex, Array.lex, n₁, n₂, Std.PRange.forIn'_eq_forIn'_toList]
rfl
@[simp, grind =] theorem lex_toArray [BEq α] {lt : α α Bool} {xs ys : Vector α n} :
@@ -92,7 +96,7 @@ instance [LT α]
Trans (· < · : Vector α n Vector α n Prop) (· < ·) (· < ·) where
trans h₁ h₂ := Vector.lt_trans h₁ h₂
protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem lt_of_le_of_lt [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -100,7 +104,7 @@ protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
{xs ys zs : Vector α n} (h₁ : xs ys) (h₂ : ys < zs) : xs < zs :=
Array.lt_of_le_of_lt h₁ h₂
protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_trans [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -108,7 +112,7 @@ protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
{xs ys zs : Vector α n} (h₁ : xs ys) (h₂ : ys zs) : xs zs :=
fun h₃ => h₁ (Vector.lt_of_le_of_lt h₂ h₃)
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -120,16 +124,16 @@ protected theorem lt_asymm [LT α]
[i : Std.Asymm (· < · : α α Prop)]
{xs ys : Vector α n} (h : xs < ys) : ¬ ys < xs := Array.lt_asymm h
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Asymm (· < · : α α Prop)] :
Std.Asymm (· < · : Vector α n Vector α n Prop) where
asymm _ _ := Vector.lt_asymm
protected theorem le_total [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_total [LT α]
[i : Std.Total (¬ · < · : α α Prop)] (xs ys : Vector α n) : xs ys ys xs :=
Array.le_total _ _
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Total (¬ · < · : α α Prop)] :
Std.Total (· · : Vector α n Vector α n Prop) where
total := Vector.le_total
@@ -137,15 +141,15 @@ instance [DecidableEq α] [LT α] [DecidableLT α]
@[simp] protected theorem not_lt [LT α]
{xs ys : Vector α n} : ¬ xs < ys ys xs := Iff.rfl
@[simp] protected theorem not_le [DecidableEq α] [LT α] [DecidableLT α]
{xs ys : Vector α n} : ¬ ys xs xs < ys := Decidable.not_not
@[simp] protected theorem not_le [LT α]
{xs ys : Vector α n} : ¬ ys xs xs < ys := Classical.not_not
protected theorem le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_of_lt [LT α]
[i : Std.Total (¬ · < · : α α Prop)]
{xs ys : Vector α n} (h : xs < ys) : xs ys :=
Array.le_of_lt h
protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_lt_or_eq [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
[Std.Total (¬ · < · : α α Prop)]
@@ -210,14 +214,14 @@ theorem lex_eq_false_iff_exists [BEq α] [PartialEquivBEq α] (lt : αα
rcases ys with ys, n₂
simp_all [Array.lex_eq_false_iff_exists]
protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Vector α n} :
protected theorem lt_iff_exists [LT α] {xs ys : Vector α n} :
xs < ys
( (i : Nat) (h : i < n), ( j, (hj : j < i) xs[j] = ys[j]) xs[i] < ys[i]) := by
cases xs
cases ys
simp_all [Array.lt_iff_exists]
protected theorem le_iff_exists [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_exists [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)] {xs ys : Vector α n} :
@@ -232,7 +236,7 @@ theorem append_left_lt [LT α] {xs : Vector α n} {ys ys' : Vector α m} (h : ys
xs ++ ys < xs ++ ys' := by
simpa using Array.append_left_lt h
theorem append_left_le [DecidableEq α] [LT α] [DecidableLT α]
theorem append_left_le [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -245,7 +249,7 @@ protected theorem map_lt [LT α] [LT β]
map f xs < map f ys := by
simpa using Array.map_lt w h
protected theorem map_le [DecidableEq α] [LT α] [DecidableLT α] [DecidableEq β] [LT β] [DecidableLT β]
protected theorem map_le [LT α] [LT β]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]

View File

@@ -362,10 +362,9 @@ instance : GetElem? (List α) Nat α fun as i => i < as.length where
theorem none_eq_getElem?_iff {l : List α} {i : Nat} : none = l[i]? length l i := by
simp [eq_comm (a := none)]
@[grind =]
theorem getElem?_eq_none (h : length l i) : l[i]? = none := getElem?_eq_none_iff.mpr h
grind_pattern List.getElem?_eq_none => l.length i, l[i]?
instance : LawfulGetElem (List α) Nat α fun as i => i < as.length where
getElem?_def as i h := by
split <;> simp_all

View File

@@ -20,6 +20,7 @@ public import Init.Grind.Ordered
public import Init.Grind.Ext
public import Init.Grind.ToInt
public import Init.Grind.ToIntLemmas
public import Init.Grind.Attr
public import Init.Data.Int.OfNat -- This may not have otherwise been imported, breaking `grind` proofs.
public section

93
src/Init/Grind/Attr.lean Normal file
View File

@@ -0,0 +1,93 @@
/-
Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Init.Tactics
public section
namespace Lean.Grind
/--
Gadget for representing generalization steps `h : x = val` in patterns
This gadget is used to represent patterns in theorems that have been generalized to reduce the
number of casts introduced during E-matching based instantiation.
For example, consider the theorem
```
Option.pbind_some {α1 : Type u_1} {a : α1} {α2 : Type u_2}
{f : (a_1 : α1) → some a = some a_1 → Option α2}
: (some a).pbind f = f a rfl
```
Now, suppose we have a goal containing the term `c.pbind g` and the equivalence class
`{c, some b}`. The E-matching module generates the instance
```
(some b).pbind (cast ⋯ g)
```
The `cast` is necessary because `g`'s type contains `c` instead of `some b.
This `cast` problematic because we don't have a systematic way of pushing casts over functions
to its arguments. Moreover, heterogeneous equality is not effective because the following theorem
is not provable in DTT:
```
theorem hcongr (h₁ : f ≍ g) (h₂ : a ≍ b) : f a ≍ g b := ...
```
The standard solution is to generalize the theorem above and write it as
```
theorem Option.pbind_some'
{α1 : Type u_1} {a : α1} {α2 : Type u_2}
{x : Option α1}
{f : (a_1 : α1) → x = some a_1 → Option α2}
(h : x = some a)
: x.pbind f = f a h := by
subst h
apply Option.pbind_some
```
Internally, we use this gadget to mark the E-matching pattern as
```
(genPattern h x (some a)).pbind f
```
This pattern is matched in the same way we match `(some a).pbind f`, but it saves the proof
for the actual term to the `some`-application in `f`, and the actual term in `x`.
In the example above, `c.pbind g` also matches the pattern `(genPattern h x (some a)).pbind f`,
and stores `c` in `x`, `b` in `a`, and the proof that `c = some b` in `h`.
-/
def genPattern {α : Sort u} (_h : Prop) (x : α) (_val : α) : α := x
/-- Similar to `genPattern` but for the heterogeneous case -/
def genHEqPattern {α β : Sort u} (_h : Prop) (x : α) (_val : β) : α := x
end Lean.Grind
namespace Lean.Parser
/--
Reset all `grind` attributes. This command is intended for testing purposes only and should not be used in applications.
-/
syntax (name := resetGrindAttrs) "reset_grind_attrs%" : command
namespace Attr
syntax grindGen := ppSpace &"gen"
syntax grindEq := "=" (grindGen)?
syntax grindEqBoth := atomic("_" "=" "_") (grindGen)?
syntax grindEqRhs := atomic("=" "_") (grindGen)?
syntax grindEqBwd := patternIgnore(atomic("" "=") <|> atomic("<-" "="))
syntax grindBwd := patternIgnore("" <|> "<-") (grindGen)?
syntax grindFwd := patternIgnore("" <|> "->")
syntax grindRL := patternIgnore("" <|> "<=")
syntax grindLR := patternIgnore("" <|> "=>")
syntax grindUsr := &"usr"
syntax grindCases := &"cases"
syntax grindCasesEager := atomic(&"cases" &"eager")
syntax grindIntro := &"intro"
syntax grindExt := &"ext"
syntax grindSym := &"symbol" ppSpace prio
syntax grindMod :=
grindEqBoth <|> grindEqRhs <|> grindEq <|> grindEqBwd <|> grindBwd
<|> grindFwd <|> grindRL <|> grindLR <|> grindUsr <|> grindCasesEager
<|> grindCases <|> grindIntro <|> grindExt <|> grindGen <|> grindSym
syntax (name := grind) "grind" (ppSpace grindMod)? : attr
syntax (name := grind?) "grind?" (ppSpace grindMod)? : attr
end Attr
end Lean.Parser

View File

@@ -131,6 +131,11 @@ theorem Bool.eq_true_of_not_eq_false' {a : Bool} (h : ¬ a = false) : a = true :
theorem Bool.false_of_not_eq_self {a : Bool} (h : (!a) = a) : False := by
by_cases a <;> simp_all
theorem Bool.ne_of_eq_true_of_eq_false {a b : Bool} (h₁ : a = true) (h₂ : b = false) : (a = b) = False := by
cases a <;> cases b <;> simp_all
theorem Bool.ne_of_eq_false_of_eq_true {a b : Bool} (h₁ : a = false) (h₂ : b = true) : (a = b) = False := by
cases a <;> cases b <;> simp_all
/- The following two helper theorems are used to case-split `a = b` representing `iff`. -/
theorem of_eq_eq_true {a b : Prop} (h : (a = b) = True) : (a b) (¬ a ¬ b) := by
by_cases a <;> by_cases b <;> simp_all

View File

@@ -20,6 +20,24 @@ class AddRightCancel (M : Type u) [Add M] where
/-- Addition is right-cancellative. -/
add_right_cancel : a b c : M, a + c = b + c a = b
class AddCommMonoid (M : Type u) extends Zero M, Add M where
/-- Zero is the right identity for addition. -/
add_zero : a : M, a + 0 = a
/-- Addition is commutative. -/
add_comm : a b : M, a + b = b + a
/-- Addition is associative. -/
add_assoc : a b c : M, a + b + c = a + (b + c)
attribute [instance 100] AddCommMonoid.toZero AddCommMonoid.toAdd
class AddCommGroup (M : Type u) extends AddCommMonoid M, Neg M, Sub M where
/-- Negation is the left inverse of addition. -/
neg_add_cancel : a : M, -a + a = 0
/-- Subtraction is addition of the negative. -/
sub_eq_add_neg : a b : M, a - b = a + -b
attribute [instance 100] AddCommGroup.toAddCommMonoid AddCommGroup.toNeg AddCommGroup.toSub
/--
A module over the natural numbers, i.e. a type with zero, addition, and scalar multiplication by natural numbers,
satisfying appropriate compatibilities.
@@ -28,25 +46,15 @@ Equivalently, an additive commutative monoid.
Use `IntModule` if the type has negation.
-/
class NatModule (M : Type u) extends Zero M, Add M, HMul Nat M M where
/-- Zero is the right identity for addition. -/
add_zero : a : M, a + 0 = a
/-- Addition is commutative. -/
add_comm : a b : M, a + b = b + a
/-- Addition is associative. -/
add_assoc : a b c : M, a + b + c = a + (b + c)
class NatModule (M : Type u) extends AddCommMonoid M where
/-- Scalar multiplication by natural numbers. -/
[nsmul : HMul Nat M M]
/-- Scalar multiplication by zero is zero. -/
zero_hmul : a : M, 0 * a = 0
/-- Scalar multiplication by one is the identity. -/
one_hmul : a : M, 1 * a = a
/-- Scalar multiplication is distributive over addition in the natural numbers. -/
add_hmul : n m : Nat, a : M, (n + m) * a = n * a + m * a
/-- Scalar multiplication of zero is zero. -/
hmul_zero : n : Nat, n * (0 : M) = 0
/-- Scalar multiplication is distributive over addition in the module. -/
hmul_add : n : Nat, a b : M, n * (a + b) = n * a + n * b
zero_nsmul : a : M, 0 * a = 0
/-- Scalar multiplication by a successor. -/
add_one_nsmul : n : Nat, a : M, (n + 1) * a = n * a + a
attribute [instance 100] NatModule.toZero NatModule.toAdd NatModule.toHMul
attribute [instance 100] NatModule.toAddCommMonoid NatModule.nsmul
/--
A module over the integers, i.e. a type with zero, addition, negation, subtraction, and scalar multiplication by integers,
@@ -54,83 +62,54 @@ satisfying appropriate compatibilities.
Equivalently, an additive commutative group.
-/
class IntModule (M : Type u) extends Zero M, Add M, Neg M, Sub M where
class IntModule (M : Type u) extends AddCommGroup M where
/-- Scalar multiplication by natural numbers. -/
[hmulNat : HMul Nat M M]
[nsmul : HMul Nat M M]
/-- Scalar multiplication by integers. -/
[hmulInt : HMul Int M M]
/-- Zero is the right identity for addition. -/
add_zero : a : M, a + 0 = a
/-- Addition is commutative. -/
add_comm : a b : M, a + b = b + a
/-- Addition is associative. -/
add_assoc : a b c : M, a + b + c = a + (b + c)
[zsmul : HMul Int M M]
/-- Scalar multiplication by zero is zero. -/
zero_hmul : a : M, (0 : Int) * a = 0
zero_zsmul : a : M, (0 : Int) * a = 0
/-- Scalar multiplication by one is the identity. -/
one_hmul : a : M, (1 : Int) * a = a
one_zsmul : a : M, (1 : Int) * a = a
/-- Scalar multiplication is distributive over addition in the integers. -/
add_hmul : n m : Int, a : M, (n + m) * a = n * a + m * a
/-- Scalar multiplication of zero is zero. -/
hmul_zero : n : Int, n * (0 : M) = 0
/-- Scalar multiplication is distributive over addition in the module. -/
hmul_add : n : Int, a b : M, n * (a + b) = n * a + n * b
/-- Negation is the left inverse of addition. -/
neg_add_cancel : a : M, -a + a = 0
/-- Subtraction is addition of the negative. -/
sub_eq_add_neg : a b : M, a - b = a + -b
add_zsmul : n m : Int, a : M, (n + m) * a = n * a + m * a
/-- Scalar multiplication by natural numbers is consistent with scalar multiplication by integers. -/
hmul_nat : n : Nat, a : M, (n : Int) * a = n * a
zsmul_natCast_eq_nsmul : n : Nat, a : M, (n : Int) * a = n * a
namespace NatModule
variable {M : Type u} [NatModule M]
theorem zero_add (a : M) : 0 + a = a := by
rw [add_comm, add_zero]
theorem mul_hmul (n m : Nat) (a : M) : (n * m) * a = n * (m * a) := by
induction n with
| zero => simp [zero_hmul]
| succ n ih =>
rw [Nat.add_one_mul, add_hmul, ih, add_hmul, one_hmul]
instance (priority := 100) (M : Type u) [NatModule M] : SMul Nat M where
smul a x := a * x
end NatModule
attribute [instance 100] IntModule.toAddCommGroup IntModule.zsmul
namespace IntModule
attribute [instance 100] IntModule.toZero IntModule.toAdd IntModule.toNeg IntModule.toSub
IntModule.hmulNat IntModule.hmulInt
instance toNatModule (M : Type u) [i : IntModule M] : NatModule M :=
{ i with
hMul := i.hmulNat.hMul
zero_hmul := by simp [ hmul_nat, zero_hmul]
one_hmul := by simp [ hmul_nat, one_hmul]
hmul_zero := by simp [ hmul_nat, hmul_zero]
add_hmul := by simp [ hmul_nat, add_hmul]
hmul_add := by simp [ hmul_nat, hmul_add] }
instance (priority := 100) (M : Type u) [IntModule M] : SMul Nat M where
smul a x := a * x
instance (priority := 100) (M : Type u) [IntModule M] : SMul Int M where
smul a x := a * x
variable {M : Type u} [IntModule M]
instance (priority := 100) toNatModule [I : IntModule M] : NatModule M :=
{ I with
zero_nsmul a := by rw [ zsmul_natCast_eq_nsmul, Int.natCast_zero, zero_zsmul]
add_one_nsmul n a := by rw [ zsmul_natCast_eq_nsmul, Int.natCast_add_one, add_zsmul,
zsmul_natCast_eq_nsmul, one_zsmul] }
end IntModule
namespace AddCommMonoid
variable {M : Type u} [AddCommMonoid M]
theorem zero_add (a : M) : 0 + a = a := by
rw [add_comm, add_zero]
theorem add_neg_cancel (a : M) : a + -a = 0 := by
rw [add_comm, neg_add_cancel]
theorem add_left_comm (a b c : M) : a + (b + c) = b + (a + c) := by
rw [ add_assoc, add_assoc, add_comm a]
end AddCommMonoid
namespace AddCommGroup
variable {M : Type u} [AddCommGroup M]
open AddCommMonoid
theorem add_neg_cancel (a : M) : a + -a = 0 := by
rw [add_comm, neg_add_cancel]
theorem add_left_inj {a b : M} (c : M) : a + c = b + c a = b :=
fun h => by simpa [add_assoc, add_neg_cancel, add_zero] using (congrArg (· + -c) h),
fun g => congrArg (· + c) g
@@ -175,35 +154,95 @@ theorem add_sub_cancel {a b : M} : a + b - b = a := by
theorem sub_add_cancel {a b : M} : a - b + b = a := by
rw [sub_eq_add_neg, add_assoc, neg_add_cancel, add_zero]
theorem neg_hmul (n : Int) (a : M) : (-n) * a = - (n * a) := by
theorem neg_eq_iff (a b : M) : -a = b a = -b := by
constructor
· intro h
rw [ neg_neg a, h]
· intro h
rw [ neg_neg b, h]
end AddCommGroup
namespace NatModule
variable {M : Type u} [NatModule M]
theorem one_nsmul (a : M) : 1 * a = a := by
rw [ Nat.zero_add 1, add_one_nsmul, zero_nsmul, AddCommMonoid.zero_add]
theorem add_nsmul (n m : Nat) (a : M) : (n + m) * a = n * a + m * a := by
induction m with
| zero => rw [Nat.add_zero, zero_nsmul, AddCommMonoid.add_zero]
| succ m ih => rw [add_one_nsmul, Nat.add_assoc, add_one_nsmul, ih, AddCommMonoid.add_assoc]
theorem nsmul_zero (n : Nat) : n * (0 : M) = 0 := by
induction n with
| zero => rw [zero_nsmul]
| succ n ih => rw [add_one_nsmul, ih, AddCommMonoid.zero_add]
theorem nsmul_add (n : Nat) (a b : M) : n * (a + b) = n * a + n * b := by
induction n with
| zero => rw [zero_nsmul, zero_nsmul, zero_nsmul, AddCommMonoid.zero_add]
| succ n ih => rw [add_one_nsmul, add_one_nsmul, add_one_nsmul, ih, AddCommMonoid.add_assoc,
AddCommMonoid.add_left_comm (n * b), AddCommMonoid.add_assoc]
theorem mul_nsmul (n m : Nat) (a : M) : (n * m) * a = n * (m * a) := by
induction n with
| zero => simp [zero_nsmul]
| succ n ih =>
rw [Nat.add_one_mul, add_nsmul, ih, add_nsmul, one_nsmul]
instance (priority := 100) (M : Type u) [NatModule M] : SMul Nat M where
smul a x := a * x
end NatModule
namespace IntModule
open NatModule AddCommGroup
instance (priority := 100) (M : Type u) [IntModule M] : SMul Int M where
smul a x := a * x
variable {M : Type u} [IntModule M]
theorem neg_zsmul (n : Int) (a : M) : (-n) * a = - (n * a) := by
apply (add_left_inj (n * a)).mp
rw [ add_hmul, Int.add_left_neg, zero_hmul, neg_add_cancel]
rw [ add_zsmul, Int.add_left_neg, zero_zsmul, neg_add_cancel]
theorem hmul_neg (n : Int) (a : M) : n * (-a) = - (n * a) := by
theorem zsmul_zero (n : Int) : n * (0 : M) = 0 := by
match n with
| (n : Nat) => rw [zsmul_natCast_eq_nsmul, NatModule.nsmul_zero]
| -(n + 1 : Nat) => rw [neg_zsmul, zsmul_natCast_eq_nsmul, NatModule.nsmul_zero, neg_zero]
theorem zsmul_add (n : Int) (a b : M) : n * (a + b) = n * a + n * b := by
match n with
| (n : Nat) => rw [zsmul_natCast_eq_nsmul, NatModule.nsmul_add, zsmul_natCast_eq_nsmul, zsmul_natCast_eq_nsmul]
| -(n + 1 : Nat) => rw [neg_zsmul, zsmul_natCast_eq_nsmul, NatModule.nsmul_add,
neg_zsmul, zsmul_natCast_eq_nsmul, neg_zsmul, zsmul_natCast_eq_nsmul, neg_add]
theorem zsmul_neg (n : Int) (a : M) : n * (-a) = - (n * a) := by
apply (add_left_inj (n * a)).mp
rw [ hmul_add, neg_add_cancel, neg_add_cancel, hmul_zero]
rw [ zsmul_add, neg_add_cancel, neg_add_cancel, zsmul_zero]
theorem hmul_sub (k : Int) (a b : M) : k * (a - b) = k * a - k * b := by
rw [sub_eq_add_neg, hmul_add, hmul_neg, sub_eq_add_neg]
theorem zsmul_sub (k : Int) (a b : M) : k * (a - b) = k * a - k * b := by
rw [sub_eq_add_neg, zsmul_add, zsmul_neg, sub_eq_add_neg]
theorem sub_hmul (k₁ k₂ : Int) (a : M) : (k₁ - k₂) * a = k₁ * a - k₂ * a := by
rw [Int.sub_eq_add_neg, add_hmul, neg_hmul, sub_eq_add_neg]
theorem sub_zsmul (k₁ k₂ : Int) (a : M) : (k₁ - k₂) * a = k₁ * a - k₂ * a := by
rw [Int.sub_eq_add_neg, add_zsmul, neg_zsmul, sub_eq_add_neg]
theorem nat_zero_hmul (a : M) : (0 : Nat) * a = 0 := by
rw [ hmul_nat, Int.natCast_zero, zero_hmul]
private theorem nat_mul_hmul (n : Nat) (m : Int) (a : M) :
private theorem mul_zsmul_aux (n : Nat) (m : Int) (a : M) :
((n : Int) * m) * a = (n : Int) * (m * a) := by
induction n with
| zero => simp [zero_hmul]
| zero => simp [zero_zsmul]
| succ n ih =>
rw [Int.natCast_add, Int.add_mul, add_hmul, Int.natCast_one,
Int.one_mul, add_hmul, one_hmul, ih]
rw [Int.natCast_add, Int.add_mul, add_zsmul, Int.natCast_one,
Int.one_mul, add_zsmul, one_zsmul, ih]
theorem mul_hmul (n m : Int) (a : M) : (n * m) * a = n * (m * a) := by
theorem mul_zsmul (n m : Int) (a : M) : (n * m) * a = n * (m * a) := by
match n with
| (n : Nat) => exact nat_mul_hmul n m a
| -(n + 1 : Nat) => rw [Int.neg_mul, neg_hmul, nat_mul_hmul, neg_hmul]
| (n : Nat) => exact mul_zsmul_aux n m a
| -(n + 1 : Nat) => rw [Int.neg_mul, neg_zsmul, mul_zsmul_aux, neg_zsmul]
end IntModule
@@ -216,7 +255,7 @@ For a module over the integers this is equivalent to
(See the alternative constructor `NoNatZeroDivisors.mk'`,
and the theorem `eq_zero_of_mul_eq_zero`.)
-/
class NoNatZeroDivisors (α : Type u) [HMul Nat α α] where
class NoNatZeroDivisors (α : Type u) [NatModule α] where
/-- If `k * a ≠ k * b` then `k ≠ 0` or `a ≠ b`.-/
no_nat_zero_divisors : (k : Nat) (a b : α), k 0 k * a = k * b a = b
@@ -225,31 +264,35 @@ export NoNatZeroDivisors (no_nat_zero_divisors)
namespace NoNatZeroDivisors
/-- Alternative constructor for `NoNatZeroDivisors` when we have an `IntModule`. -/
def mk' {α} [IntModule α] (eq_zero_of_mul_eq_zero : (k : Nat) (a : α), k 0 k * a = 0 a = 0) : NoNatZeroDivisors α where
def mk' {α} [IntModule α]
(eq_zero_of_mul_eq_zero : (k : Nat) (a : α), k 0 k * a = 0 a = 0) :
NoNatZeroDivisors α where
no_nat_zero_divisors k a b h₁ h₂ := by
rw [ IntModule.sub_eq_zero_iff, IntModule.hmul_nat, IntModule.hmul_nat, IntModule.hmul_sub, IntModule.hmul_nat] at h₂
rw [ IntModule.sub_eq_zero_iff]
rw [ AddCommGroup.sub_eq_zero_iff, IntModule.zsmul_natCast_eq_nsmul,
IntModule.zsmul_natCast_eq_nsmul, IntModule.zsmul_sub,
IntModule.zsmul_natCast_eq_nsmul] at h₂
rw [ AddCommGroup.sub_eq_zero_iff]
apply eq_zero_of_mul_eq_zero k (a - b) h₁ h₂
theorem eq_zero_of_mul_eq_zero {α : Type u} [NatModule α] [NoNatZeroDivisors α] {k : Nat} {a : α}
: k 0 k * a = 0 a = 0 := by
intro h₁ h₂
replace h₁ : k 0 := by intro h; simp [h] at h₁
exact no_nat_zero_divisors k a 0 h₁ (by rwa [NatModule.hmul_zero])
exact no_nat_zero_divisors k a 0 h₁ (by rwa [NatModule.nsmul_zero])
end NoNatZeroDivisors
instance [ToInt α (IntInterval.co lo hi)] [IntModule α] [ToInt.Zero α (IntInterval.co lo hi)] [ToInt.Add α (IntInterval.co lo hi)] : ToInt.Neg α (IntInterval.co lo hi) where
instance [ToInt α (IntInterval.co lo hi)] [AddCommGroup α] [ToInt.Zero α (IntInterval.co lo hi)] [ToInt.Add α (IntInterval.co lo hi)] : ToInt.Neg α (IntInterval.co lo hi) where
toInt_neg x := by
have := (ToInt.Add.toInt_add (-x) x).symm
rw [IntModule.neg_add_cancel, ToInt.Zero.toInt_zero, ToInt.Zero.wrap_zero (α := α)] at this
rw [AddCommGroup.neg_add_cancel, ToInt.Zero.toInt_zero, ToInt.Zero.wrap_zero (α := α)] at this
rw [IntInterval.wrap_eq_wrap_iff] at this
simp at this
rw [ ToInt.wrap_toInt]
rw [IntInterval.wrap_eq_wrap_iff]
simpa
instance [ToInt α (IntInterval.co lo hi)] [IntModule α] [ToInt.Add α (IntInterval.co lo hi)] [ToInt.Neg α (IntInterval.co lo hi)] : ToInt.Sub α (IntInterval.co lo hi) :=
ToInt.Sub.of_sub_eq_add_neg IntModule.sub_eq_add_neg (by simp)
instance [ToInt α (IntInterval.co lo hi)] [AddCommGroup α] [ToInt.Add α (IntInterval.co lo hi)] [ToInt.Neg α (IntInterval.co lo hi)] : ToInt.Sub α (IntInterval.co lo hi) :=
ToInt.Sub.of_sub_eq_add_neg AddCommGroup.sub_eq_add_neg (by simp)
end Lean.Grind

View File

@@ -19,9 +19,9 @@ variable [NatModule α]
-- Helper instance for `ac_rfl`
local instance : Std.Associative (· + · : α α α) where
assoc := NatModule.add_assoc
assoc := AddCommMonoid.add_assoc
local instance : Std.Commutative (· + · : α α α) where
comm := NatModule.add_comm
comm := AddCommMonoid.add_comm
@[local simp] private theorem exists_true : (_ : α), True := 0, trivial
@@ -33,10 +33,10 @@ def Q := Quot (r α)
variable {α}
theorem r_rfl (a : α × α) : r α a a := by
cases a; refine 0, ?_; simp [NatModule.add_zero]; ac_rfl
cases a; refine 0, ?_; simp [AddCommMonoid.add_zero]; ac_rfl
theorem r_sym {a b : α × α} : r α a b r α b a := by
cases a; cases b; simp [r]; intro h w; refine h, ?_; simp [w, NatModule.add_comm]
cases a; cases b; simp [r]; intro h w; refine h, ?_; simp [w, AddCommMonoid.add_comm]
theorem r_trans {a b c : α × α} : r α a b r α b c r α a c := by
cases a; cases b; cases c;
@@ -63,20 +63,20 @@ def Q.liftOn₂ (q₁ q₂ : Q α)
induction q₂ using Quot.ind
apply h; assumption; apply r_rfl
attribute [local simp] Q.mk Q.liftOn₂ NatModule.add_zero
attribute [local simp] Q.mk Q.liftOn₂ AddCommMonoid.add_zero
def Q.ind {β : Q α Prop} (mk : (a : α × α), β (Q.mk a)) (q : Q α) : β q :=
Quot.ind mk q
@[local simp] def hmulNat (n : Nat) (q : Q α) : (Q α) :=
@[local simp] def nsmul (n : Nat) (q : Q α) : (Q α) :=
q.liftOn (fun (a, b) => Q.mk (n * a, n * b))
(by intro (a₁, b₁) (a₂, b₂)
simp; intro k h; apply Quot.sound; simp
refine n * k, ?_
replace h := congrArg (fun x : α => n * x) h
simpa [NatModule.hmul_add] using h)
simpa [NatModule.nsmul_add] using h)
@[local simp] def hmulInt (n : Int) (q : Q α) : (Q α) :=
@[local simp] def zsmul (n : Int) (q : Q α) : (Q α) :=
q.liftOn (fun (a, b) => if n < 0 then Q.mk (n.natAbs * b, n.natAbs * a) else Q.mk (n.natAbs * a, n.natAbs * b))
(by intro (a₁, b₁) (a₂, b₂)
simp; intro k h;
@@ -84,11 +84,11 @@ def Q.ind {β : Q α → Prop} (mk : ∀ (a : α × α), β (Q.mk a)) (q : Q α)
· apply Quot.sound; simp
refine n.natAbs * k, ?_
replace h := congrArg (fun x : α => n.natAbs * x) h
simpa [NatModule.hmul_add] using h.symm
simpa [NatModule.nsmul_add] using h.symm
· apply Quot.sound; simp
refine n.natAbs * k, ?_
replace h := congrArg (fun x : α => n.natAbs * x) h
simpa [NatModule.hmul_add] using h)
simpa [NatModule.nsmul_add] using h)
@[local simp] def sub (q₁ q₂ : Q α) : Q α :=
Q.liftOn₂ q₁ q₂ (fun (a, b) (c, d) => Q.mk (a + d, c + b))
@@ -115,8 +115,8 @@ def Q.ind {β : Q α → Prop} (mk : ∀ (a : α × α), β (Q.mk a)) (q : Q α)
exact k, h.symm)
attribute [local simp]
Quot.liftOn NatModule.add_zero NatModule.zero_add NatModule.one_hmul NatModule.zero_hmul NatModule.hmul_zero
NatModule.hmul_add NatModule.add_hmul
Quot.liftOn AddCommMonoid.add_zero AddCommMonoid.zero_add NatModule.one_nsmul NatModule.zero_nsmul NatModule.nsmul_zero
NatModule.nsmul_add NatModule.add_nsmul
@[local simp] def zero : Q α :=
Q.mk (0, 0)
@@ -150,29 +150,15 @@ theorem sub_eq_add_neg (a b : Q α) : sub a b = add a (neg b) := by
next a b =>
cases a; cases b; simp; apply Quot.sound; simp; refine 0, ?_; ac_rfl
theorem one_hmul (a : Q α) : hmulInt 1 a = a := by
theorem one_zsmul (a : Q α) : zsmul 1 a = a := by
induction a using Quot.ind
next a => cases a; simp
theorem zero_hmul (a : Q α) : hmulInt 0 a = zero := by
theorem zero_zsmul (a : Q α) : zsmul 0 a = zero := by
induction a using Quot.ind
next a => cases a; simp
theorem hmul_zero (a : Int) : hmulInt a (zero : Q α) = zero := by
simp
theorem hmul_add (a : Int) (b c : Q α) : hmulInt a (add b c) = add (hmulInt a b) (hmulInt a c) := by
induction b using Q.ind
induction c using Q.ind
next b c =>
cases b; cases c; simp
split <;>
· apply Quot.sound
refine 0, ?_
simp
ac_rfl
theorem add_hmul (a b : Int) (c : Q α) : hmulInt (a + b) c = add (hmulInt a c) (hmulInt b c) := by
theorem add_zsmul (a b : Int) (c : Q α) : zsmul (a + b) c = add (zsmul a c) (zsmul b c) := by
induction c using Q.ind
next c =>
rcases c with c₁, c₂; simp
@@ -183,7 +169,7 @@ theorem add_hmul (a b : Int) (c : Q α) : hmulInt (a + b) c = add (hmulInt a c)
rw [if_pos (by omega)]
apply Quot.sound
refine 0, ?_
rw [Int.natAbs_add_of_nonpos (by omega) (by omega), NatModule.add_hmul, NatModule.add_hmul]
rw [Int.natAbs_add_of_nonpos (by omega) (by omega), NatModule.add_nsmul, NatModule.add_nsmul]
ac_rfl
· split
· apply Quot.sound
@@ -213,23 +199,23 @@ theorem add_hmul (a b : Int) (c : Q α) : hmulInt (a + b) c = add (hmulInt a c)
rw [if_neg (by omega)]
apply Quot.sound
refine 0, ?_
rw [Int.natAbs_add_of_nonneg (by omega) (by omega), NatModule.add_hmul, NatModule.add_hmul]
rw [Int.natAbs_add_of_nonneg (by omega) (by omega), NatModule.add_nsmul, NatModule.add_nsmul]
ac_rfl
theorem hmul_nat (n : Nat) (a : Q α) : hmulInt (n : Int) a = hmulNat n a := by
theorem zsmul_natCast_eq_nsmul (n : Nat) (a : Q α) : zsmul (n : Int) a = nsmul n a := by
induction a using Q.ind
next a =>
rcases a with a₁, a₂; simp; omega
def ofNatModule : IntModule (Q α) := {
hmulNat := hmulNat,
hmulInt := hmulInt,
nsmul := nsmul,
zsmul := zsmul,
zero,
add, sub, neg,
add_comm, add_assoc, add_zero,
neg_add_cancel, sub_eq_add_neg,
one_hmul, zero_hmul, hmul_zero, hmul_add, add_hmul,
hmul_nat
one_zsmul, zero_zsmul, add_zsmul,
zsmul_natCast_eq_nsmul
}
attribute [instance] ofNatModule
@@ -257,7 +243,7 @@ private def rel (h : Equivalence (r α)) (q₁ q₂ : Q α) : Prop :=
private theorem rel_rfl (h : Equivalence (r α)) (q : Q α) : rel h q q := by
induction q using Quot.ind
simp [rel, NatModule.add_comm]
simp [rel, AddCommMonoid.add_comm]
private theorem helper (h : Equivalence (r α)) (q₁ q₂ : Q α) : q₁ = q₂ rel h q₁ q₂ := by
intro h; subst q₁; apply rel_rfl h
@@ -287,7 +273,7 @@ instance [NatModule α] [AddRightCancel α] [NoNatZeroDivisors α] : NoNatZeroDi
simp [r] at h₂
rcases h₂ with k', h₂
replace h₂ := AddRightCancel.add_right_cancel _ _ _ h₂
simp [ NatModule.hmul_add] at h₂
simp [ NatModule.nsmul_add] at h₂
replace h₂ := NoNatZeroDivisors.no_nat_zero_divisors k (a₁ + b₂) (a₂ + b₁) h₁ h₂
apply Quot.sound; simp [r]; exists 0; simp [h₂]
@@ -318,7 +304,7 @@ instance [Preorder α] [OrderedAdd α] : Preorder (OfNatModule.Q α) where
rcases a with a₁, a₂
change Q.mk _ Q.mk _
simp only [mk_le_mk]
simp [NatModule.add_comm]; exact Preorder.le_refl (a₁ + a₂)
simp [AddCommMonoid.add_comm]; exact Preorder.le_refl (a₁ + a₂)
le_trans {a b c} h₁ h₂ := by
induction a using Q.ind
induction b using Q.ind
@@ -337,12 +323,12 @@ attribute [-simp] Q.mk
@[local simp] private theorem mk_lt_mk [Preorder α] [OrderedAdd α] {a₁ a₂ b₁ b₂ : α} :
Q.mk (a₁, a₂) < Q.mk (b₁, b₂) a₁ + b₂ < a₂ + b₁ := by
simp [Preorder.lt_iff_le_not_le, NatModule.add_comm]
simp [Preorder.lt_iff_le_not_le, AddCommMonoid.add_comm]
@[local simp] private theorem mk_pos [Preorder α] [OrderedAdd α] {a₁ a₂ : α} :
0 < Q.mk (a₁, a₂) a₂ < a₁ := by
change Q.mk (0,0) < _ _
simp [mk_lt_mk, NatModule.zero_add]
simp [mk_lt_mk, AddCommMonoid.zero_add]
@[local simp]
theorem toQ_le [Preorder α] [OrderedAdd α] {a b : α} : toQ a toQ b a b := by

View File

@@ -45,11 +45,19 @@ theorem imp_true_eq (p : Prop) : (p → True) = True := by simp
theorem imp_false_eq (p : Prop) : (p False) = ¬p := by simp
theorem imp_self_eq (p : Prop) : (p p) = True := by simp
theorem not_and (p q : Prop) : (¬(p q)) = (¬p ¬q) := by
by_cases p <;> by_cases q <;> simp [*]
theorem not_true : (¬True) = False := by simp
theorem not_false : (¬False) = True := by simp
theorem not_not (p : Prop) : (¬¬p) = p := by by_cases p <;> simp [*]
theorem not_and (p q : Prop) : (¬(p q)) = (¬p ¬q) := by by_cases p <;> by_cases q <;> simp [*]
theorem not_or (p q : Prop) : (¬(p q)) = (¬p ¬q) := by by_cases p <;> by_cases q <;> simp [*]
theorem not_ite {_ : Decidable p} (q r : Prop) : (¬ite p q r) = ite p (¬q) (¬r) := by by_cases p <;> simp [*]
theorem not_forall (p : α Prop) : (¬ x, p x) = x, ¬p x := by simp
theorem not_exists (p : α Prop) : (¬ x, p x) = x, ¬p x := by simp
theorem not_implies (p q : Prop) : (¬(p q)) = (p ¬q) := by simp
theorem not_ite {_ : Decidable p} (q r : Prop) : (¬ite p q r) = ite p (¬q) (¬r) := by
by_cases p <;> simp [*]
theorem or_assoc (p q r : Prop) : ((p q) r) = (p (q r)) := by by_cases p <;> simp [*]
theorem or_swap12 (p q r : Prop) : (p q r) = (q p r) := by by_cases p <;> simp [*]
theorem or_swap13 (p q r : Prop) : (p q r) = (r q p) := by by_cases p <;> by_cases q <;> simp [*]
theorem ite_true_false {_ : Decidable p} : (ite p True False) = p := by
by_cases p <;> simp
@@ -57,10 +65,6 @@ theorem ite_true_false {_ : Decidable p} : (ite p True False) = p := by
theorem ite_false_true {_ : Decidable p} : (ite p False True) = ¬p := by
by_cases p <;> simp
theorem not_forall (p : α Prop) : (¬ x, p x) = x, ¬p x := by simp
theorem not_exists (p : α Prop) : (¬ x, p x) = x, ¬p x := by simp
theorem cond_eq_ite (c : Bool) (a b : α) : cond c a b = ite c a b := by
cases c <;> simp [*]
@@ -70,9 +74,6 @@ theorem Nat.lt_eq (a b : Nat) : (a < b) = (a + 1 ≤ b) := by
theorem Int.lt_eq (a b : Int) : (a < b) = (a + 1 b) := by
simp [Int.lt, LT.lt]
theorem ge_eq [LE α] (a b : α) : (a b) = (b a) := rfl
theorem gt_eq [LT α] (a b : α) : (a > b) = (b < a) := rfl
theorem beq_eq_decide_eq {_ : BEq α} [LawfulBEq α] [DecidableEq α] (a b : α) : (a == b) = (decide (a = b)) := by
by_cases a = b
next h => simp [h]
@@ -81,14 +82,11 @@ theorem beq_eq_decide_eq {_ : BEq α} [LawfulBEq α] [DecidableEq α] (a b : α)
theorem bne_eq_decide_not_eq {_ : BEq α} [LawfulBEq α] [DecidableEq α] (a b : α) : (a != b) = (decide (¬ a = b)) := by
by_cases a = b <;> simp [*]
theorem xor_eq (a b : Bool) : (a ^^ b) = (a != b) := by
rfl
theorem natCast_eq [NatCast α] (a : Nat) : (Nat.cast a : α) = (NatCast.natCast a : α) := rfl
theorem natCast_div (a b : Nat) : (NatCast.natCast (a / b) : Int) = (NatCast.natCast a) / (NatCast.natCast b) := rfl
theorem natCast_mod (a b : Nat) : (NatCast.natCast (a % b) : Int) = (NatCast.natCast a) % (NatCast.natCast b) := rfl
theorem natCast_add (a b : Nat) : (NatCast.natCast (a + b : Nat) : Int) = (NatCast.natCast a : Int) + (NatCast.natCast b : Int) := rfl
theorem natCast_mul (a b : Nat) : (NatCast.natCast (a * b : Nat) : Int) = (NatCast.natCast a : Int) * (NatCast.natCast b : Int) := rfl
theorem natCast_pow (a b : Nat) : (NatCast.natCast (a ^ b : Nat) : Int) = (NatCast.natCast a : Int) ^ b := by simp
theorem Nat.pow_one (a : Nat) : a ^ 1 = a := by
simp
@@ -127,52 +125,49 @@ theorem forall_forall_or {α : Sort u} {β : α → Sort v} (p : α → Prop) (q
intro h'; simp at h'; have b, h₁, h₂ := h'
replace h := h a b; simp [h₁, h₂] at h
theorem forall_and {α} {p q : α Prop} : ( x, p x q x) = (( x, p x) ( x, q x)) := by
apply propext; apply _root_.forall_and
theorem exists_const (α : Sort u) [i : Nonempty α] {b : Prop} : ( _ : α, b) = b := by
apply propext; apply _root_.exists_const
theorem exists_or {α : Sort u} {p q : α Prop} : ( x, p x q x) = (( x, p x) x, q x) := by
apply propext; apply _root_.exists_or
theorem exists_prop {a b : Prop} : ( _h : a, b) = (a b) := by
apply propext; apply _root_.exists_prop
theorem exists_and_left {α : Sort u} {p : α Prop} {b : Prop} : ( x, b p x) = (b ( x, p x)) := by
apply propext; apply _root_.exists_and_left
theorem exists_and_right {α : Sort u} {p : α Prop} {b : Prop} : ( x, p x b) = (( x, p x) b) := by
apply propext; apply _root_.exists_and_right
theorem zero_sub (a : Nat) : 0 - a = 0 := by
simp
-- Remark: for additional `grind` simprocs, check `Lean/Meta/Tactic/Grind`
init_grind_norm
/- Pre theorems -/
not_and not_or not_ite not_forall not_exists
/- Nat relational ops neg -/
Nat.not_ge_eq Nat.not_le_eq
|
/- Post theorems -/
Classical.not_not
ne_eq iff_eq eq_self heq_eq_eq
forall_or_forall forall_forall_or
-- Prop equality
eq_true_eq eq_false_eq not_eq_prop
-- True
not_true
-- False
not_false_eq_true
-- Implication
true_imp_eq false_imp_eq imp_true_eq imp_false_eq imp_self_eq
iff_eq heq_eq_eq
-- And
and_true true_and and_false false_and and_assoc
-- Or
or_true true_or or_false false_or or_assoc
-- ite
ite_true ite_false ite_true_false ite_false_true
dite_eq_ite
-- Forall
forall_and forall_false forall_true
forall_imp_eq_or
-- Exists
exists_const exists_or exists_prop exists_and_left exists_and_right
ite_true_false ite_false_true
-- Bool cond
cond_eq_ite
-- Bool or
Bool.or_false Bool.or_true Bool.false_or Bool.true_or Bool.or_eq_true Bool.or_assoc
Bool.or_false Bool.or_true Bool.false_or Bool.true_or Bool.or_eq_true
-- Bool and
Bool.and_false Bool.and_true Bool.false_and Bool.true_and Bool.and_eq_true Bool.and_assoc
Bool.and_false Bool.and_true Bool.false_and Bool.true_and Bool.and_eq_true
-- Bool not
Bool.not_not
-- Bool xor
xor_eq
-- beq
beq_iff_eq beq_eq_decide_eq beq_self_eq_true
-- bne
bne_iff_ne bne_eq_decide_not_eq
-- Bool not eq true/false
Bool.not_eq_true Bool.not_eq_false
-- decide
decide_eq_true_eq decide_not not_decide_eq_true
-- Nat
@@ -180,19 +175,17 @@ init_grind_norm
Nat.add_eq Nat.sub_eq Nat.mul_eq Nat.zero_eq Nat.le_eq
Nat.div_zero Nat.mod_zero Nat.div_one Nat.mod_one
Nat.sub_sub Nat.pow_zero Nat.pow_one Nat.sub_self
Nat.one_pow
Nat.one_pow Nat.zero_sub
-- Int
Int.lt_eq
Int.emod_neg Int.ediv_neg
Int.ediv_zero Int.emod_zero
Int.ediv_one Int.emod_one
Int.negSucc_eq
natCast_eq natCast_div natCast_mod
natCast_add natCast_mul
natCast_div natCast_mod
natCast_add natCast_mul natCast_pow
Int.one_pow
Int.pow_zero Int.pow_one
-- GT GE
ge_eq gt_eq
-- Int op folding
Int.add_def Int.mul_def Int.ofNat_eq_coe
Int.Linear.sub_fold Int.Linear.neg_fold
@@ -202,6 +195,6 @@ init_grind_norm
Function.const_apply Function.comp_apply Function.const_comp
Function.comp_const Function.true_comp Function.false_comp
-- Field
Field.div_eq_mul_inv Field.inv_zero Field.inv_inv Field.inv_one Field.inv_neg
Field.inv_zero Field.inv_inv Field.inv_one Field.inv_neg
end Lean.Grind

View File

@@ -20,9 +20,9 @@ Support for the linear arithmetic module for `IntModule` in `grind`
namespace Lean.Grind.Linarith
abbrev Var := Nat
open IntModule
open AddCommMonoid AddCommGroup NatModule IntModule
attribute [local simp] add_zero zero_add zero_hmul nat_zero_hmul hmul_zero one_hmul
attribute [local simp] add_zero zero_add zero_zsmul zero_nsmul zsmul_zero one_zsmul
inductive Expr where
| zero
@@ -75,10 +75,10 @@ where
-- Helper instance for `ac_rfl`
local instance {α} [IntModule α] : Std.Associative (· + · : α α α) where
assoc := IntModule.add_assoc
assoc := AddCommMonoid.add_assoc
-- Helper instance for `ac_rfl`
local instance {α} [IntModule α] : Std.Commutative (· + · : α α α) where
comm := IntModule.add_comm
comm := AddCommMonoid.add_comm
theorem Poly.denote'_go_eq_denote {α} [IntModule α] (ctx : Context α) (p : Poly) (r : α) : denote'.go ctx r p = p.denote ctx + r := by
induction r, p using denote'.go.induct ctx <;> simp [denote'.go, denote]
@@ -176,7 +176,7 @@ def Poly.mul (p : Poly) (k : Int) : Poly :=
next => simp [*, denote]
next =>
induction p <;> simp [mul', denote, *]
rw [mul_hmul, hmul_add]
rw [mul_zsmul, zsmul_add]
theorem Poly.denote_insert {α} [IntModule α] (ctx : Context α) (k : Int) (v : Var) (p : Poly) :
(p.insert k v).denote ctx = p.denote ctx + k * v.denote ctx := by
@@ -184,8 +184,8 @@ theorem Poly.denote_insert {α} [IntModule α] (ctx : Context α) (k : Int) (v :
next => ac_rfl
next h₁ h₂ h₃ =>
simp at h₃; simp at h₂; subst h₂
rw [add_comm, add_assoc, add_hmul, h₃, zero_hmul, zero_add]
next h _ => simp at h; subst h; rw [add_hmul]; ac_rfl
rw [add_comm, add_assoc, add_zsmul, h₃, zero_zsmul, zero_add]
next h _ => simp at h; subst h; rw [add_zsmul]; ac_rfl
next ih => rw [ih]; ac_rfl
attribute [local simp] Poly.denote_insert
@@ -205,8 +205,8 @@ theorem Poly.denote_combine' {α} [IntModule α] (ctx : Context α) (fuel : Nat)
simp_all +zetaDelta [denote]
next h _ =>
rw [Int.add_comm] at h
rw [add_left_comm, add_assoc, add_assoc, add_hmul, h, zero_hmul, zero_add]
next => rw [add_hmul]; ac_rfl
rw [add_left_comm, add_assoc, add_assoc, add_zsmul, h, zero_zsmul, zero_add]
next => rw [add_zsmul]; ac_rfl
all_goals ac_rfl
theorem Poly.denote_combine {α} [IntModule α] (ctx : Context α) (p₁ p₂ : Poly) : (p₁.combine p₂).denote ctx = p₁.denote ctx + p₂.denote ctx := by
@@ -216,14 +216,14 @@ attribute [local simp] Poly.denote_combine
theorem Expr.denote_toPoly'_go {α} [IntModule α] {k p} (ctx : Context α) (e : Expr)
: (toPoly'.go k e p).denote ctx = k * e.denote ctx + p.denote ctx := by
induction k, e using Expr.toPoly'.go.induct generalizing p <;> simp [toPoly'.go, denote, Poly.denote, *, hmul_add]
induction k, e using Expr.toPoly'.go.induct generalizing p <;> simp [toPoly'.go, denote, Poly.denote, *, zsmul_add]
next => ac_rfl
next => rw [sub_eq_add_neg, neg_hmul, hmul_add, hmul_neg]; ac_rfl
next => rw [sub_eq_add_neg, neg_zsmul, zsmul_add, zsmul_neg]; ac_rfl
next h => simp at h; subst h; simp
next ih => simp at ih; rw [ih, mul_hmul, IntModule.hmul_nat]
next ih => simp at ih; rw [ih, mul_zsmul, zsmul_natCast_eq_nsmul]
next ih => simp at ih; simp [ih]
next ih => simp at ih; rw [ih, mul_hmul]
next => rw [hmul_neg, neg_hmul]
next ih => simp at ih; rw [ih, mul_zsmul]
next => rw [zsmul_neg, neg_zsmul]
theorem Expr.denote_norm {α} [IntModule α] (ctx : Context α) (e : Expr) : e.norm.denote ctx = e.denote ctx := by
simp [norm, toPoly', Expr.denote_toPoly'_go, Poly.denote]
@@ -280,8 +280,8 @@ def le_le_combine_cert (p₁ p₂ p₃ : Poly) : Bool :=
theorem le_le_combine {α} [IntModule α] [Preorder α] [OrderedAdd α] (ctx : Context α) (p₁ p₂ p₃ : Poly)
: le_le_combine_cert p₁ p₂ p₃ p₁.denote' ctx 0 p₂.denote' ctx 0 p₃.denote' ctx 0 := by
simp [le_le_combine_cert]; intro _ h₁ h₂; subst p₃; simp
replace h₁ := hmul_int_nonpos (coe_natAbs_nonneg p₂.leadCoeff) h₁
replace h₂ := hmul_int_nonpos (coe_natAbs_nonneg p₁.leadCoeff) h₂
replace h₁ := zsmul_nonpos (coe_natAbs_nonneg p₂.leadCoeff) h₁
replace h₂ := zsmul_nonpos (coe_natAbs_nonneg p₁.leadCoeff) h₂
exact le_add_le h₁ h₂
def le_lt_combine_cert (p₁ p₂ p₃ : Poly) : Bool :=
@@ -292,8 +292,8 @@ def le_lt_combine_cert (p₁ p₂ p₃ : Poly) : Bool :=
theorem le_lt_combine {α} [IntModule α] [Preorder α] [OrderedAdd α] (ctx : Context α) (p₁ p₂ p₃ : Poly)
: le_lt_combine_cert p₁ p₂ p₃ p₁.denote' ctx 0 p₂.denote' ctx < 0 p₃.denote' ctx < 0 := by
simp [-Int.natAbs_pos, -Int.ofNat_pos, le_lt_combine_cert]; intro hp _ h₁ h₂; subst p₃; simp
replace h₁ := hmul_int_nonpos (coe_natAbs_nonneg p₂.leadCoeff) h₁
replace h₂ := hmul_int_neg_iff (p₁.leadCoeff.natAbs) h₂ |>.mpr hp
replace h₁ := zsmul_nonpos (coe_natAbs_nonneg p₂.leadCoeff) h₁
replace h₂ := zsmul_neg_iff (p₁.leadCoeff.natAbs) h₂ |>.mpr hp
exact le_add_lt h₁ h₂
def lt_lt_combine_cert (p₁ p₂ p₃ : Poly) : Bool :=
@@ -304,8 +304,8 @@ def lt_lt_combine_cert (p₁ p₂ p₃ : Poly) : Bool :=
theorem lt_lt_combine {α} [IntModule α] [Preorder α] [OrderedAdd α] (ctx : Context α) (p₁ p₂ p₃ : Poly)
: lt_lt_combine_cert p₁ p₂ p₃ p₁.denote' ctx < 0 p₂.denote' ctx < 0 p₃.denote' ctx < 0 := by
simp [-Int.natAbs_pos, -Int.ofNat_pos, lt_lt_combine_cert]; intro hp₁ hp₂ _ h₁ h₂; subst p₃; simp
replace h₁ := hmul_int_neg_iff (p₂.leadCoeff.natAbs) h₁ |>.mpr hp₁
replace h₂ := hmul_int_neg_iff (p₁.leadCoeff.natAbs) h₂ |>.mpr hp₂
replace h₁ := zsmul_neg_iff (p₂.leadCoeff.natAbs) h₁ |>.mpr hp₁
replace h₂ := zsmul_neg_iff (p₁.leadCoeff.natAbs) h₂ |>.mpr hp₂
exact lt_add_lt h₁ h₂
def diseq_split_cert (p₁ p₂ : Poly) : Bool :=
@@ -320,7 +320,7 @@ theorem diseq_split {α} [IntModule α] [LinearOrder α] [OrderedAdd α] (ctx :
next h =>
apply Or.inr
simp [h₁] at h
rw [ neg_pos_iff, neg_hmul, neg_neg, one_hmul]; assumption
rw [ neg_pos_iff, neg_zsmul, neg_neg, one_zsmul]; assumption
theorem diseq_split_resolve {α} [IntModule α] [LinearOrder α] [OrderedAdd α] (ctx : Context α) (p₁ p₂ : Poly)
: diseq_split_cert p₁ p₂ p₁.denote' ctx 0 ¬p₁.denote' ctx < 0 p₂.denote' ctx < 0 := by
@@ -409,7 +409,7 @@ theorem eq_of_le_ge {α} [IntModule α] [PartialOrder α] [OrderedAdd α] (ctx :
intro; subst p₂; simp
intro h₁ h₂
replace h₂ := add_le_left h₂ (p₁.denote ctx)
rw [add_comm, neg_hmul, one_hmul, sub_eq_add_neg, sub_self, zero_add] at h₂
rw [add_comm, neg_zsmul, one_zsmul, sub_eq_add_neg, sub_self, zero_add] at h₂
exact PartialOrder.le_antisymm h₁ h₂
/-!
@@ -429,7 +429,7 @@ def zero_lt_one_cert (p : Poly) : Bool :=
theorem zero_lt_one {α} [Ring α] [Preorder α] [OrderedRing α] (ctx : Context α) (p : Poly)
: zero_lt_one_cert p (0 : Var).denote ctx = One.one p.denote' ctx < 0 := by
simp [zero_lt_one_cert]; intro _ h; subst p; simp [Poly.denote, h, One.one, neg_hmul]
simp [zero_lt_one_cert]; intro _ h; subst p; simp [Poly.denote, h, One.one, neg_zsmul]
rw [neg_lt_iff, neg_zero]; apply OrderedRing.zero_lt_one
def zero_ne_one_cert (p : Poly) : Bool :=
@@ -478,7 +478,7 @@ def eq_coeff_cert (p₁ p₂ : Poly) (k : Nat) :=
theorem eq_coeff {α} [IntModule α] [NoNatZeroDivisors α] (ctx : Context α) (p₁ p₂ : Poly) (k : Nat)
: eq_coeff_cert p₁ p₂ k p₁.denote' ctx = 0 p₂.denote' ctx = 0 := by
simp [eq_coeff_cert]; intro h _; subst p₁; simp [*, hmul_nat]
simp [eq_coeff_cert]; intro h _; subst p₁; simp [*, zsmul_natCast_eq_nsmul]
exact NoNatZeroDivisors.eq_zero_of_mul_eq_zero h
def coeff_cert (p₁ p₂ : Poly) (k : Nat) :=
@@ -490,7 +490,7 @@ theorem le_coeff {α} [IntModule α] [LinearOrder α] [OrderedAdd α] (ctx : Con
have : k > (0 : Int) := Int.natCast_pos.mpr h
intro h₁; apply Classical.byContradiction
intro h₂; replace h₂ := LinearOrder.lt_of_not_le h₂
replace h₂ := hmul_int_pos_iff (k) h₂ |>.mpr this
replace h₂ := zsmul_pos_iff (k) h₂ |>.mpr this
exact Preorder.lt_irrefl 0 (Preorder.lt_of_lt_of_le h₂ h₁)
theorem lt_coeff {α} [IntModule α] [LinearOrder α] [OrderedAdd α] (ctx : Context α) (p₁ p₂ : Poly) (k : Nat)
@@ -499,11 +499,11 @@ theorem lt_coeff {α} [IntModule α] [LinearOrder α] [OrderedAdd α] (ctx : Con
have : k > (0 : Int) := Int.natCast_pos.mpr h
intro h₁; apply Classical.byContradiction
intro h₂; replace h₂ := LinearOrder.le_of_not_lt h₂
replace h₂ := hmul_int_nonneg (Int.le_of_lt this) h₂
replace h₂ := zsmul_nonneg (Int.le_of_lt this) h₂
exact Preorder.lt_irrefl 0 (Preorder.lt_of_le_of_lt h₂ h₁)
theorem diseq_neg {α} [IntModule α] (ctx : Context α) (p p' : Poly) : p' == p.mul (-1) p.denote' ctx 0 p'.denote' ctx 0 := by
simp; intro _ _; subst p'; simp [neg_hmul]
simp; intro _ _; subst p'; simp [neg_zsmul]
intro h; replace h := congrArg (- ·) h; simp [neg_neg, neg_zero] at h
contradiction
@@ -522,8 +522,8 @@ theorem eq_diseq_subst {α} [IntModule α] [NoNatZeroDivisors α] (ctx : Context
have : (k₁.natAbs : Int) * Poly.denote ctx p₂ = 0 := by
cases Int.natAbs_eq_iff.mp (Eq.refl k₁.natAbs)
next h => rw [ h]; assumption
next h => replace h := congrArg (- ·) h; simp at h; rw [ h, IntModule.neg_hmul, h₃, IntModule.neg_zero]
simpa [hmul_nat] using this
next h => replace h := congrArg (- ·) h; simp at h; rw [ h, neg_zsmul, h₃, neg_zero]
simpa [zsmul_natCast_eq_nsmul] using this
have := NoNatZeroDivisors.eq_zero_of_mul_eq_zero hne this
contradiction
@@ -547,7 +547,7 @@ def eq_le_subst_cert (x : Var) (p₁ p₂ p₃ : Poly) :=
theorem eq_le_subst {α} [IntModule α] [Preorder α] [OrderedAdd α] (ctx : Context α) (x : Var) (p₁ p₂ p₃ : Poly)
: eq_le_subst_cert x p₁ p₂ p₃ p₁.denote' ctx = 0 p₂.denote' ctx 0 p₃.denote' ctx 0 := by
simp [eq_le_subst_cert]; intro h _ h₁ h₂; subst p₃; simp [h₁]
exact hmul_int_nonpos h h₂
exact zsmul_nonpos h h₂
def eq_lt_subst_cert (x : Var) (p₁ p₂ p₃ : Poly) :=
let a := p₁.coeff x
@@ -557,7 +557,7 @@ def eq_lt_subst_cert (x : Var) (p₁ p₂ p₃ : Poly) :=
theorem eq_lt_subst {α} [IntModule α] [Preorder α] [OrderedAdd α] (ctx : Context α) (x : Var) (p₁ p₂ p₃ : Poly)
: eq_lt_subst_cert x p₁ p₂ p₃ p₁.denote' ctx = 0 p₂.denote' ctx < 0 p₃.denote' ctx < 0 := by
simp [eq_lt_subst_cert]; intro h _ h₁ h₂; subst p₃; simp [h₁]
exact hmul_int_neg_iff (p₁.coeff x) h₂ |>.mpr h
exact zsmul_neg_iff (p₁.coeff x) h₂ |>.mpr h
def eq_eq_subst_cert (x : Var) (p₁ p₂ p₃ : Poly) :=
let a := p₁.coeff x

View File

@@ -26,22 +26,15 @@ class ExistsAddOfLT (α : Type u) [LT α] [Zero α] [Add α] where
namespace OrderedAdd
open NatModule
open AddCommMonoid NatModule
section
variable {M : Type u} [Preorder M] [NatModule M] [OrderedAdd M]
variable {M : Type u} [Preorder M] [AddCommMonoid M] [OrderedAdd M]
theorem add_le_right_iff {a b : M} (c : M) : a b c + a c + b := by
rw [add_comm c a, add_comm c b, add_le_left_iff]
theorem hmul_le_hmul {k : Nat} {a b : M} (h : a b) : k * a k * b := by
induction k with
| zero => simp [zero_hmul, Preorder.le_refl]
| succ k ih =>
rw [add_hmul, one_hmul, add_hmul, one_hmul]
exact Preorder.le_trans ((add_le_left_iff a).mp ih) ((add_le_right_iff (k * b)).mp h)
theorem add_le_left {a b : M} (h : a b) (c : M) : a + c b + c :=
(add_le_left_iff c).mp h
@@ -73,36 +66,6 @@ theorem add_lt_left_iff {a b : M} (c : M) : a < b ↔ a + c < b + c := by
theorem add_lt_right_iff {a b : M} (c : M) : a < b c + a < c + b := by
rw [add_comm c a, add_comm c b, add_lt_left_iff]
theorem hmul_lt_hmul_iff (k : Nat) {a b : M} (h : a < b) : k * a < k * b 0 < k := by
induction k with
| zero => simp [zero_hmul, Preorder.lt_irrefl]
| succ k ih =>
rw [add_hmul, one_hmul, add_hmul, one_hmul]
simp only [Nat.zero_lt_succ, iff_true]
by_cases hk : 0 < k
· simp only [hk, iff_true] at ih
exact Preorder.lt_trans ((add_lt_left_iff a).mp ih) ((add_lt_right_iff (k * b)).mp h)
· simp [Nat.eq_zero_of_not_pos hk, zero_hmul, zero_add, h]
theorem hmul_pos_iff {k : Nat} {a : M} (h : 0 < a) : 0 < k * a 0 < k:= by
rw [ hmul_lt_hmul_iff k h, hmul_zero]
theorem hmul_nonneg {k : Nat} {a : M} (h : 0 a) : 0 k * a := by
have := hmul_le_hmul (k := k) h
rwa [hmul_zero] at this
theorem hmul_le_hmul_of_le_of_le_of_nonneg
{k₁ k₂ : Nat} {x y : M} (hk : k₁ k₂) (h : x y) (w : 0 x) :
k₁ * x k₂ * y := by
apply Preorder.le_trans
· change k₁ * x k₂ * x
obtain k', rfl := Nat.exists_eq_add_of_le hk
rw [add_hmul]
conv => lhs; rw [ add_zero (k₁ * x)]
rw [ add_le_right_iff]
exact hmul_nonneg w
· exact hmul_le_hmul h
theorem add_le_add {a b c d : M} (hab : a b) (hcd : c d) : a + c b + d :=
Preorder.le_trans (add_le_right a hcd) (add_le_left hab d)
@@ -110,44 +73,90 @@ end
section
variable {M : Type u} [Preorder M] [IntModule M] [OrderedAdd M]
variable {M : Type u} [Preorder M] [NatModule M] [OrderedAdd M]
theorem nsmul_le_nsmul {k : Nat} {a b : M} (h : a b) : k * a k * b := by
induction k with
| zero => simp [zero_nsmul, Preorder.le_refl]
| succ k ih =>
rw [add_nsmul, one_nsmul, add_nsmul, one_nsmul]
exact Preorder.le_trans ((add_le_left_iff a).mp ih) ((add_le_right_iff (k * b)).mp h)
theorem nsmul_lt_nsmul_iff (k : Nat) {a b : M} (h : a < b) : k * a < k * b 0 < k := by
induction k with
| zero => simp [zero_nsmul, Preorder.lt_irrefl]
| succ k ih =>
rw [add_nsmul, one_nsmul, add_nsmul, one_nsmul]
simp only [Nat.zero_lt_succ, iff_true]
by_cases hk : 0 < k
· simp only [hk, iff_true] at ih
exact Preorder.lt_trans ((add_lt_left_iff a).mp ih) ((add_lt_right_iff (k * b)).mp h)
· simp [Nat.eq_zero_of_not_pos hk, zero_nsmul, zero_add, h]
theorem nsmul_pos_iff {k : Nat} {a : M} (h : 0 < a) : 0 < k * a 0 < k:= by
rw [ nsmul_lt_nsmul_iff k h, nsmul_zero]
theorem nsmul_nonneg {k : Nat} {a : M} (h : 0 a) : 0 k * a := by
have := nsmul_le_nsmul (k := k) h
rwa [nsmul_zero] at this
theorem nsmul_le_nsmul_of_le_of_le_of_nonneg
{k₁ k₂ : Nat} {x y : M} (hk : k₁ k₂) (h : x y) (w : 0 x) :
k₁ * x k₂ * y := by
apply Preorder.le_trans
· change k₁ * x k₂ * x
obtain k', rfl := Nat.exists_eq_add_of_le hk
rw [add_nsmul]
conv => lhs; rw [ add_zero (k₁ * x)]
rw [ add_le_right_iff]
exact nsmul_nonneg w
· exact nsmul_le_nsmul h
end
section
open AddCommGroup
variable {M : Type u} [Preorder M] [AddCommGroup M] [OrderedAdd M]
theorem neg_le_iff {a b : M} : -a b -b a := by
rw [OrderedAdd.add_le_left_iff a, IntModule.neg_add_cancel]
conv => rhs; rw [OrderedAdd.add_le_left_iff b, IntModule.neg_add_cancel]
rw [OrderedAdd.add_le_left_iff a, neg_add_cancel]
conv => rhs; rw [OrderedAdd.add_le_left_iff b, neg_add_cancel]
rw [add_comm]
end
section
variable {M : Type u} [Preorder M] [IntModule M] [OrderedAdd M]
open AddCommGroup IntModule
theorem hmul_int_pos_iff (k : Int) {x : M} (h : 0 < x) : 0 < k * x 0 < k :=
theorem zsmul_pos_iff (k : Int) {x : M} (h : 0 < x) : 0 < k * x 0 < k :=
match k with
| (k + 1 : Nat) => by
simpa [IntModule.hmul_zero, IntModule.hmul_nat] using hmul_lt_hmul_iff (k := k + 1) h
| (0 : Nat) => by simp [IntModule.zero_hmul]; exact Preorder.lt_irrefl 0
simpa [zsmul_zero, zsmul_natCast_eq_nsmul] using nsmul_lt_nsmul_iff (k := k + 1) h
| (0 : Nat) => by simp [zero_zsmul]; exact Preorder.lt_irrefl 0
| -(k + 1 : Nat) => by
have : ¬ (k : Int) + 1 < 0 := by omega
simp [this]; clear this
rw [IntModule.neg_hmul]
rw [neg_zsmul]
rw [Preorder.lt_iff_le_not_le]
simp
intro h'
rw [OrderedAdd.neg_le_iff, IntModule.neg_zero]
simpa [IntModule.hmul_zero, IntModule.hmul_nat] using
hmul_le_hmul (k := k + 1) (Preorder.le_of_lt h)
rw [OrderedAdd.neg_le_iff, neg_zero]
simpa [zsmul_zero, zsmul_natCast_eq_nsmul] using
nsmul_le_nsmul (k := k + 1) (Preorder.le_of_lt h)
theorem hmul_int_nonneg {k : Int} {x : M} (h : 0 k) (hx : 0 x) : 0 k * x :=
theorem zsmul_nonneg {k : Int} {x : M} (h : 0 k) (hx : 0 x) : 0 k * x :=
match k, h with
| (k : Nat), _ => by
simpa [IntModule.hmul_nat] using OrderedAdd.hmul_nonneg hx
simpa [zsmul_natCast_eq_nsmul] using nsmul_nonneg hx
end
variable {M : Type u} [Preorder M] [IntModule M] [OrderedAdd M]
section
variable {M : Type u} [Preorder M] [AddCommGroup M] [OrderedAdd M]
open IntModule
open AddCommGroup
theorem le_neg_iff {a b : M} : a -b b -a := by
conv => lhs; rw [ neg_neg a]
@@ -168,31 +177,40 @@ theorem neg_pos_iff {a : M} : 0 < -a ↔ a < 0 := by
rw [lt_neg_iff, neg_zero]
theorem sub_nonneg_iff {a b : M} : 0 a - b b a := by
rw [add_le_left_iff b, IntModule.zero_add, sub_add_cancel]
rw [add_le_left_iff b, zero_add, sub_add_cancel]
theorem sub_pos_iff {a b : M} : 0 < a - b b < a := by
rw [add_lt_left_iff b, IntModule.zero_add, sub_add_cancel]
rw [add_lt_left_iff b, zero_add, sub_add_cancel]
theorem hmul_int_neg_iff (k : Int) {a : M} (h : a < 0) : k * a < 0 0 < k := by
simpa [IntModule.hmul_neg, neg_pos_iff] using hmul_int_pos_iff k (neg_pos_iff.mpr h)
end
theorem hmul_int_nonpos {k : Int} {a : M} (hk : 0 k) (ha : a 0) : k * a 0 := by
simpa [IntModule.hmul_neg, neg_nonneg_iff] using hmul_int_nonneg hk (neg_nonneg_iff.mpr ha)
section
theorem hmul_int_le_hmul_int {a b : M} {k : Int} (hk : 0 k) (h : a b) : k * a k * b := by
simpa [hmul_sub, sub_nonneg_iff] using hmul_int_nonneg hk (sub_nonneg_iff.mpr h)
variable {M : Type u} [Preorder M] [IntModule M] [OrderedAdd M]
open IntModule
theorem hmul_int_lt_hmul_int_iff (k : Int) {a b : M} (h : a < b) : k * a < k * b 0 < k := by
simpa [hmul_sub, sub_pos_iff] using hmul_int_pos_iff k (sub_pos_iff.mpr h)
theorem zsmul_neg_iff (k : Int) {a : M} (h : a < 0) : k * a < 0 0 < k := by
simpa [IntModule.zsmul_neg, neg_pos_iff] using zsmul_pos_iff k (neg_pos_iff.mpr h)
theorem hmul_int_le_hmul_int_of_le_of_le_of_nonneg_of_nonneg
theorem zsmul_nonpos {k : Int} {a : M} (hk : 0 k) (ha : a 0) : k * a 0 := by
simpa [IntModule.zsmul_neg, neg_nonneg_iff] using zsmul_nonneg hk (neg_nonneg_iff.mpr ha)
theorem zsmul_le_zsmul {a b : M} {k : Int} (hk : 0 k) (h : a b) : k * a k * b := by
simpa [zsmul_sub, sub_nonneg_iff] using zsmul_nonneg hk (sub_nonneg_iff.mpr h)
theorem zsmul_lt_zsmul_iff (k : Int) {a b : M} (h : a < b) : k * a < k * b 0 < k := by
simpa [zsmul_sub, sub_pos_iff] using zsmul_pos_iff k (sub_pos_iff.mpr h)
theorem zsmul_le_zsmul_of_le_of_le_of_nonneg_of_nonneg
{k₁ k₂ : Int} {x y : M} (hk : k₁ k₂) (h : x y) (w : 0 k₁) (w' : 0 x) :
k₁ * x k₂ * y := by
apply Preorder.le_trans
· have : 0 k₁ * (y - x) := hmul_int_nonneg w (sub_nonneg_iff.mpr h)
rwa [IntModule.hmul_sub, sub_nonneg_iff] at this
· have : 0 (k₂ - k₁) * y := hmul_int_nonneg (Int.sub_nonneg.mpr hk) (Preorder.le_trans w' h)
rwa [IntModule.sub_hmul, sub_nonneg_iff] at this
· have : 0 k₁ * (y - x) := zsmul_nonneg w (sub_nonneg_iff.mpr h)
rwa [IntModule.zsmul_sub, sub_nonneg_iff] at this
· have : 0 (k₂ - k₁) * y := zsmul_nonneg (Int.sub_nonneg.mpr hk) (Preorder.le_trans w' h)
rwa [IntModule.sub_zsmul, sub_nonneg_iff] at this
end
end OrderedAdd

View File

@@ -38,7 +38,7 @@ variable [Preorder R] [OrderedRing R]
theorem neg_one_lt_zero : (-1 : R) < 0 := by
have h := zero_lt_one (R := R)
have := OrderedAdd.add_lt_left h (-1)
rw [Semiring.zero_add, Ring.add_neg_cancel] at this
rw [AddCommMonoid.zero_add, AddCommGroup.add_neg_cancel] at this
assumption
theorem ofNat_nonneg (x : Nat) : (OfNat.ofNat x : R) 0 := by
@@ -48,7 +48,7 @@ theorem ofNat_nonneg (x : Nat) : (OfNat.ofNat x : R) ≥ 0 := by
have := OrderedRing.zero_lt_one (R := R)
rw [Semiring.ofNat_succ]
replace ih := OrderedAdd.add_le_left ih 1
rw [Semiring.zero_add] at ih
rw [AddCommMonoid.zero_add] at ih
have := Preorder.lt_of_lt_of_le this ih
exact Preorder.le_of_lt this
@@ -62,8 +62,8 @@ instance [Ring α] [Preorder α] [OrderedRing α] : IsCharP α 0 := IsCharP.mk'
next x =>
rw [Semiring.ofNat_succ] at h
replace h := congrArg (· - 1) h; simp at h
rw [Ring.sub_eq_add_neg, Semiring.add_assoc, Ring.add_neg_cancel,
Ring.sub_eq_add_neg, Semiring.zero_add, Semiring.add_zero] at h
rw [Ring.sub_eq_add_neg, Semiring.add_assoc, AddCommGroup.add_neg_cancel,
Ring.sub_eq_add_neg, AddCommMonoid.zero_add, Semiring.add_zero] at h
have h₁ : (OfNat.ofNat x : α) < 0 := by
have := OrderedRing.neg_one_lt_zero (R := α)
rw [h]; assumption
@@ -110,26 +110,26 @@ open OrderedAdd
theorem mul_le_mul_of_nonpos_left {a b c : R} (h : a b) (h' : c 0) : c * b c * a := by
have := mul_le_mul_of_nonneg_left h (neg_nonneg_iff.mpr h')
rwa [Ring.neg_mul, Ring.neg_mul, neg_le_iff, IntModule.neg_neg] at this
rwa [Ring.neg_mul, Ring.neg_mul, neg_le_iff, AddCommGroup.neg_neg] at this
theorem mul_le_mul_of_nonpos_right {a b c : R} (h : a b) (h' : c 0) : b * c a * c := by
have := mul_le_mul_of_nonneg_right h (neg_nonneg_iff.mpr h')
rwa [Ring.mul_neg, Ring.mul_neg, neg_le_iff, IntModule.neg_neg] at this
rwa [Ring.mul_neg, Ring.mul_neg, neg_le_iff, AddCommGroup.neg_neg] at this
theorem mul_lt_mul_of_neg_left {a b c : R} (h : a < b) (h' : c < 0) : c * b < c * a := by
have := mul_lt_mul_of_pos_left h (neg_pos_iff.mpr h')
rwa [Ring.neg_mul, Ring.neg_mul, neg_lt_iff, IntModule.neg_neg] at this
rwa [Ring.neg_mul, Ring.neg_mul, neg_lt_iff, AddCommGroup.neg_neg] at this
theorem mul_lt_mul_of_neg_right {a b c : R} (h : a < b) (h' : c < 0) : b * c < a * c := by
have := mul_lt_mul_of_pos_right h (neg_pos_iff.mpr h')
rwa [Ring.mul_neg, Ring.mul_neg, neg_lt_iff, IntModule.neg_neg] at this
rwa [Ring.mul_neg, Ring.mul_neg, neg_lt_iff, AddCommGroup.neg_neg] at this
theorem mul_nonneg {a b : R} (h₁ : 0 a) (h₂ : 0 b) : 0 a * b := by
simpa [Semiring.zero_mul] using mul_le_mul_of_nonneg_right h₁ h₂
theorem mul_nonneg_of_nonpos_of_nonpos {a b : R} (h₁ : a 0) (h₂ : b 0) : 0 a * b := by
have := mul_nonneg (neg_nonneg_iff.mpr h₁) (neg_nonneg_iff.mpr h₂)
simpa [Ring.neg_mul, Ring.mul_neg, Ring.neg_neg] using this
simpa [Ring.neg_mul, Ring.mul_neg, AddCommGroup.neg_neg] using this
theorem mul_nonpos_of_nonneg_of_nonpos {a b : R} (h₁ : 0 a) (h₂ : b 0) : a * b 0 := by
rw [ neg_nonneg_iff, Ring.mul_neg]
@@ -144,7 +144,7 @@ theorem mul_pos {a b : R} (h₁ : 0 < a) (h₂ : 0 < b) : 0 < a * b := by
theorem mul_pos_of_neg_of_neg {a b : R} (h₁ : a < 0) (h₂ : b < 0) : 0 < a * b := by
have := mul_pos (neg_pos_iff.mpr h₁) (neg_pos_iff.mpr h₂)
simpa [Ring.neg_mul, Ring.mul_neg, Ring.neg_neg] using this
simpa [Ring.neg_mul, Ring.mul_neg, AddCommGroup.neg_neg] using this
theorem mul_neg_of_pos_of_neg {a b : R} (h₁ : 0 < a) (h₂ : b < 0) : a * b < 0 := by
rw [ neg_pos_iff, Ring.mul_neg]

View File

@@ -15,7 +15,7 @@ public import Init.Grind.Module.Basic
public section
/-!
# A monolithic commutative ring typeclass for internal use in `grind`.
# Commutative ring typeclasses for internal use in `grind`.
The `Lean.Grind.CommRing` class will be used to convert expressions into the internal representation via polynomials,
with coefficients expressed via `OfNat` and `Neg`.
@@ -41,7 +41,7 @@ Use `Ring` instead if the type also has negation,
`CommSemiring` if the multiplication is commutative,
or `CommRing` if the type has negation and multiplication is commutative.
-/
class Semiring (α : Type u) extends Add α, Mul α, HPow α Nat α where
class Semiring (α : Type u) extends Add α, Mul α where
/--
In every semiring there is a canonical map from the natural numbers to the semiring,
providing the values of `0` and `1`. Note that this function need not be injective.
@@ -52,12 +52,16 @@ class Semiring (α : Type u) extends Add α, Mul α, HPow α Nat α where
The field `ofNat_eq_natCast` ensures that these are (propositionally) equal to the values of `natCast`.
-/
[ofNat : n, OfNat α n]
/-- Addition is associative. -/
add_assoc : a b c : α, a + b + c = a + (b + c)
/-- Addition is commutative. -/
add_comm : a b : α, a + b = b + a
/-- Scalar multiplication by natural numbers. -/
[nsmul : HMul Nat α α]
/-- Exponentiation by a natural number. -/
[npow : HPow α Nat α]
/-- Zero is the right identity for addition. -/
add_zero : a : α, a + 0 = a
/-- Addition is commutative. -/
add_comm : a b : α, a + b = b + a
/-- Addition is associative. -/
add_assoc : a b c : α, a + b + c = a + (b + c)
/-- Multiplication is associative. -/
mul_assoc : a b c : α, a * b * c = a * (b * c)
/-- One is the right identity for multiplication. -/
@@ -80,6 +84,7 @@ class Semiring (α : Type u) extends Add α, Mul α, HPow α Nat α where
ofNat_succ : a : Nat, OfNat.ofNat (α := α) (a + 1) = OfNat.ofNat a + 1 := by intros; rfl
/-- Numerals are consistently defined with respect to the canonical map from natural numbers. -/
ofNat_eq_natCast : n : Nat, OfNat.ofNat (α := α) n = Nat.cast n := by intros; rfl
nsmul_eq_natCast_mul : n : Nat, a : α, HMul.hMul (α := Nat) n a = Nat.cast n * a := by intros; rfl
/--
A ring, i.e. a type equipped with addition, negation, multiplication, and a map from the integers,
@@ -90,10 +95,16 @@ Use `CommRing` if the multiplication is commutative.
class Ring (α : Type u) extends Semiring α, Neg α, Sub α where
/-- In every ring there is a canonical map from the integers to the ring. -/
[intCast : IntCast α]
/-- Scalar multiplication by integers. -/
[zsmul : HMul Int α α]
/-- Negation is the left inverse of addition. -/
neg_add_cancel : a : α, -a + a = 0
/-- Subtraction is addition of the negative. -/
sub_eq_add_neg : a b : α, a - b = a + -b
/-- Scalar multiplication by the negation of an integer is the negation of scalar multiplication by that integer. -/
neg_zsmul : (i : Int) (a : α), HMul.hMul (α := Int) (-i : Int) a = -(HMul.hMul (α := Int) i a)
/-- Scalar multiplication by natural numbers is consistent with scalar multiplication by integers. -/
zsmul_natCast_eq_nsmul : n : Nat, a : α, HMul.hMul (α := Int) (n : Int) a = HMul.hMul (α := Nat) n a := by intros; rfl
/-- The canonical map from the integers is consistent with the canonical map from the natural numbers. -/
intCast_ofNat : n : Nat, Int.cast (OfNat.ofNat (α := Int) n) = OfNat.ofNat (α := α) n := by intros; rfl
/-- The canonical map from the integers is consistent with negation. -/
@@ -120,7 +131,7 @@ class CommRing (α : Type u) extends Ring α, CommSemiring α
-- so that in downstream libraries with their own `CommRing` class,
-- the path `CommRing -> Add` is found before `CommRing -> Lean.Grind.CommRing -> Add`.
-- (And similarly for the other parents.)
attribute [instance 100] Semiring.toAdd Semiring.toMul Semiring.toHPow Ring.toNeg Ring.toSub
attribute [instance 100] Semiring.toAdd Semiring.toMul Semiring.npow Ring.toNeg Ring.toSub
-- This is a low-priority instance, to avoid conflicts with existing `OfNat`, `NatCast`, and `IntCast` instances.
attribute [instance 100] Semiring.ofNat
@@ -132,27 +143,30 @@ example [CommRing α] : (CommSemiring.toSemiring : Semiring α) = (Ring.toSemiri
namespace Semiring
open NatModule
variable {α : Type u} [Semiring α]
theorem natCast_zero : ((0 : Nat) : α) = 0 := (ofNat_eq_natCast 0).symm
theorem natCast_zero : ((0 : Nat) : α) = 0 := by
rw [ ofNat_eq_natCast 0]
theorem natCast_one : ((1 : Nat) : α) = 1 := (ofNat_eq_natCast 1).symm
theorem ofNat_add (a b : Nat) : OfNat.ofNat (α := α) (a + b) = OfNat.ofNat a + OfNat.ofNat b := by
induction b with
| zero => simp [Nat.add_zero, add_zero]
| zero => rw [Nat.add_zero, add_zero]
| succ b ih => rw [Nat.add_succ, ofNat_succ, ih, ofNat_succ b, add_assoc]
instance toNatModule [I : Semiring α] : NatModule α :=
{ I with
zero_nsmul a := by rw [nsmul_eq_natCast_mul, ofNat_eq_natCast, zero_mul]
add_one_nsmul n a := by rw [nsmul_eq_natCast_mul, ofNat_eq_natCast, ofNat_add, right_distrib,
ofNat_eq_natCast, nsmul_eq_natCast_mul, ofNat_eq_natCast, natCast_one, one_mul] }
theorem natCast_add (a b : Nat) : ((a + b : Nat) : α) = ((a : α) + (b : α)) := by
rw [ ofNat_eq_natCast, ofNat_eq_natCast, ofNat_add, ofNat_eq_natCast, ofNat_eq_natCast]
theorem natCast_succ (n : Nat) : ((n + 1 : Nat) : α) = ((n : α) + 1) := by
rw [natCast_add, natCast_one]
theorem zero_add (a : α) : 0 + a = a := by
rw [add_comm, add_zero]
theorem add_left_comm (a b c : α) : a + (b + c) = b + (a + c) := by
rw [ add_assoc, add_assoc, add_comm a]
theorem ofNat_mul (a b : Nat) : OfNat.ofNat (α := α) (a * b) = OfNat.ofNat a * OfNat.ofNat b := by
induction b with
| zero => simp [Nat.mul_zero, mul_zero]
@@ -177,84 +191,29 @@ theorem natCast_pow (x : Nat) (k : Nat) : ((x ^ k : Nat) : α) = (x : α) ^ k :=
next => simp [pow_zero, Nat.pow_zero, natCast_one]
next k ih => simp [pow_succ, Nat.pow_succ, natCast_mul, *]
instance : NatModule α where
hMul a x := a * x
add_zero := by simp [add_zero]
add_assoc := by simp [add_assoc]
add_comm := by simp [add_comm]
zero_hmul := by simp [natCast_zero, zero_mul]
one_hmul := by simp [natCast_one, one_mul]
add_hmul := by simp [natCast_add, right_distrib]
hmul_zero := by simp [mul_zero]
hmul_add := by simp [left_distrib]
theorem hmul_eq_natCast_mul {α} [Semiring α] {k : Nat} {a : α} : HMul.hMul (α := Nat) k a = (k : α) * a := rfl
theorem hmul_eq_ofNat_mul {α} [Semiring α] {k : Nat} {a : α} : HMul.hMul (α := Nat) k a = OfNat.ofNat k * a := by
simp [ofNat_eq_natCast, hmul_eq_natCast_mul]
theorem nsmul_eq_ofNat_mul {α} [Semiring α] {k : Nat} {a : α} : HMul.hMul (α := Nat) k a = OfNat.ofNat k * a := by
simp [ofNat_eq_natCast, nsmul_eq_natCast_mul]
end Semiring
namespace Ring
open Semiring
open AddCommMonoid AddCommGroup NatModule IntModule
open Semiring hiding add_assoc add_comm
variable {α : Type u} [Ring α]
theorem add_neg_cancel (a : α) : a + -a = 0 := by
rw [add_comm, neg_add_cancel]
theorem add_left_inj {a b : α} (c : α) : a + c = b + c a = b :=
fun h => by simpa [add_assoc, add_neg_cancel, add_zero] using (congrArg (· + -c) h),
fun g => congrArg (· + c) g
theorem add_right_inj (a b c : α) : a + b = a + c b = c := by
rw [add_comm a b, add_comm a c, add_left_inj]
theorem neg_zero : (-0 : α) = 0 := by
rw [ add_left_inj 0, neg_add_cancel, add_zero]
theorem neg_neg (a : α) : -(-a) = a := by
rw [ add_left_inj (-a), neg_add_cancel, add_neg_cancel]
theorem neg_eq_zero (a : α) : -a = 0 a = 0 :=
fun h => by
replace h := congrArg (-·) h
simpa [neg_neg, neg_zero] using h,
fun h => by rw [h, neg_zero]
theorem neg_eq_iff (a b : α) : -a = b a = -b := by
constructor
· intro h
rw [ neg_neg a, h]
· intro h
rw [ neg_neg b, h]
theorem neg_add (a b : α) : -(a + b) = -a + -b := by
rw [ add_left_inj (a + b), neg_add_cancel, add_assoc (-a), add_comm a b, add_assoc (-b),
neg_add_cancel, zero_add, neg_add_cancel]
theorem neg_sub (a b : α) : -(a - b) = b - a := by
rw [sub_eq_add_neg, neg_add, neg_neg, sub_eq_add_neg, add_comm]
theorem sub_self (a : α) : a - a = 0 := by
rw [sub_eq_add_neg, add_neg_cancel]
theorem sub_eq_iff {a b c : α} : a - b = c a = c + b := by
rw [sub_eq_add_neg]
constructor
next => intro; subst c; rw [add_assoc, neg_add_cancel, add_zero]
next => intro; subst a; rw [add_assoc, add_comm b, neg_add_cancel, add_zero]
theorem sub_eq_zero_iff {a b : α} : a - b = 0 a = b := by
simp [sub_eq_iff, zero_add]
theorem intCast_zero : ((0 : Int) : α) = 0 := intCast_ofNat 0
theorem intCast_one : ((1 : Int) : α) = 1 := intCast_ofNat 1
theorem intCast_neg_one : ((-1 : Int) : α) = -1 := by rw [intCast_neg, intCast_ofNat]
theorem intCast_natCast (n : Nat) : ((n : Int) : α) = (n : α) := by
erw [intCast_ofNat]
rw [ofNat_eq_natCast]
instance toAddCommGroup [I : Ring α] : AddCommGroup α :=
{ I with }
theorem intCast_zero : ((0 : Int) : α) = 0 := by
rw [intCast_ofNat 0]
theorem intCast_one : ((1 : Int) : α) = 1 := intCast_ofNat 1
theorem intCast_neg_one : ((-1 : Int) : α) = -1 := by rw [intCast_neg, intCast_ofNat]
theorem intCast_natCast_add_one (n : Nat) : ((n + 1 : Int) : α) = (n : α) + 1 := by
rw [ Int.natCast_add_one, intCast_natCast, natCast_add, ofNat_eq_natCast]
theorem intCast_negSucc (n : Nat) : ((-(n + 1) : Int) : α) = -((n : α) + 1) := by
@@ -273,7 +232,8 @@ theorem intCast_nat_sub {x y : Nat} (h : x ≥ y) : (((x - y : Nat) : Int) : α)
rw [this, intCast_natCast_add_one]
specialize ih (by omega)
rw [intCast_natCast] at ih
rw [ih, natCast_succ, sub_eq_add_neg, sub_eq_add_neg, add_assoc, add_comm _ 1, add_assoc]
rw [ih, natCast_succ, sub_eq_add_neg, sub_eq_add_neg, add_assoc,
AddCommMonoid.add_comm _ 1, add_assoc]
theorem intCast_add (x y : Int) : ((x + y : Int) : α) = ((x : α) + (y : α)) :=
match x, y with
| (x : Nat), (y : Nat) => by
@@ -323,19 +283,33 @@ theorem neg_mul (a b : α) : (-a) * b = -(a * b) := by
theorem mul_neg (a b : α) : a * (-b) = -(a * b) := by
rw [neg_eq_mul_neg_one b, neg_eq_mul_neg_one (a * b), mul_assoc]
theorem intCast_nat_mul (x y : Nat) : ((x * y : Int) : α) = ((x : α) * (y : α)) := by
attribute [local instance] Ring.zsmul in
theorem zsmul_eq_intCast_mul {k : Int} {a : α} : (HMul.hMul (α := Int) (γ := α) k a : α) = (k : α) * a := by
match k with
| (k : Nat) =>
rw [intCast_natCast, zsmul_natCast_eq_nsmul, nsmul_eq_natCast_mul]
| -(k + 1 : Nat) =>
rw [intCast_neg, neg_mul, neg_zsmul, intCast_natCast, zsmul_natCast_eq_nsmul, nsmul_eq_natCast_mul]
instance toIntModule [I : Ring α] : IntModule α :=
{ I, Semiring.toNatModule (α := α) with
zero_zsmul a := by rw [ Int.natCast_zero, zsmul_natCast_eq_nsmul, zero_nsmul]
one_zsmul a := by rw [ Int.natCast_one, zsmul_natCast_eq_nsmul, one_nsmul]
add_zsmul n m a := by rw [zsmul_eq_intCast_mul, intCast_add, right_distrib, zsmul_eq_intCast_mul, zsmul_eq_intCast_mul] }
private theorem intCast_mul_aux (x y : Nat) : ((x * y : Int) : α) = ((x : α) * (y : α)) := by
rw [Int.ofNat_mul_ofNat, intCast_natCast, natCast_mul]
theorem intCast_mul (x y : Int) : ((x * y : Int) : α) = ((x : α) * (y : α)) :=
match x, y with
| (x : Nat), (y : Nat) => by
rw [intCast_nat_mul, intCast_natCast, intCast_natCast]
rw [intCast_mul_aux, intCast_natCast, intCast_natCast]
| (x : Nat), (-(y + 1 : Nat)) => by
rw [Int.mul_neg, intCast_neg, intCast_nat_mul, intCast_neg, mul_neg, intCast_natCast, intCast_natCast]
rw [Int.mul_neg, intCast_neg, intCast_mul_aux, intCast_neg, mul_neg, intCast_natCast, intCast_natCast]
| (-(x + 1 : Nat)), (y : Nat) => by
rw [Int.neg_mul, intCast_neg, intCast_nat_mul, intCast_neg, neg_mul, intCast_natCast, intCast_natCast]
rw [Int.neg_mul, intCast_neg, intCast_mul_aux, intCast_neg, neg_mul, intCast_natCast, intCast_natCast]
| (-(x + 1 : Nat)), (-(y + 1 : Nat)) => by
rw [Int.neg_mul_neg, intCast_neg, intCast_neg, neg_mul, mul_neg, neg_neg, intCast_nat_mul,
rw [Int.neg_mul_neg, intCast_neg, intCast_neg, neg_mul, mul_neg, neg_neg, intCast_mul_aux,
intCast_natCast, intCast_natCast]
theorem intCast_pow (x : Int) (k : Nat) : ((x ^ k : Int) : α) = (x : α) ^ k := by
@@ -343,27 +317,8 @@ theorem intCast_pow (x : Int) (k : Nat) : ((x ^ k : Int) : α) = (x : α) ^ k :=
next => simp [pow_zero, Int.pow_zero, intCast_one]
next k ih => simp [pow_succ, Int.pow_succ, intCast_mul, *]
instance : IntModule α where
hmulInt := fun a x => a * x
hmulNat := fun a x => a * x
hmul_nat n x := by
change ((n : Int) : α) * x = (n : α) * x
rw [intCast_natCast]
add_zero := by simp [add_zero]
add_assoc := by simp [add_assoc]
add_comm := by simp [add_comm]
zero_hmul := by simp [intCast_zero, zero_mul]
one_hmul := by simp [intCast_one, one_mul]
add_hmul := by simp [intCast_add, right_distrib]
hmul_zero := by simp [mul_zero]
hmul_add := by simp [left_distrib]
neg_add_cancel := by simp [neg_add_cancel]
sub_eq_add_neg := by simp [sub_eq_add_neg]
theorem hmul_eq_intCast_mul {α} [Ring α] {k : Int} {a : α} : HMul.hMul (α := Int) k a = (k : α) * a := rfl
-- Verify that the diamond from `Ring` to `NatModule` via either `Semiring` or `IntModule` is defeq.
example [Ring R] : (Semiring.instNatModule : NatModule R) = (IntModule.toNatModule R) := rfl
example [Ring R] : (Semiring.toNatModule : NatModule R) = IntModule.toNatModule (M := R) := rfl
end Ring
@@ -378,7 +333,9 @@ theorem mul_left_comm (a b c : α) : a * (b * c) = b * (a * c) := by
end CommSemiring
open Semiring Ring CommSemiring CommRing
open Semiring hiding add_comm add_assoc add_zero
open Ring hiding neg_add_cancel
open CommSemiring CommRing
/--
A ring `α` has characteristic `p` if `OfNat.ofNat x = 0` iff `x % p = 0`.
@@ -450,6 +407,8 @@ end Semiring
section Ring
open AddCommMonoid AddCommGroup
variable (p) {α : Type u} [Ring α] [IsCharP α p]
private theorem mk'_aux {x y : Nat} (p : Nat) (h : y x) :
@@ -525,7 +484,8 @@ theorem intCast_ext_iff {x y : Int} : (x : α) = (y : α) ↔ x % p = y % p := b
have : ((x - y : Int) : α) = 0 :=
(intCast_eq_zero_iff p _).mpr (by rw [Int.sub_emod, h, Int.sub_self, Int.zero_emod])
replace this := congrArg (· + (y : α)) this
simpa [intCast_sub, zero_add, sub_eq_add_neg, add_assoc, neg_add_cancel, add_zero] using this
simpa [intCast_sub, zero_add, AddCommGroup.sub_eq_add_neg, add_assoc,
neg_add_cancel, add_zero] using this
theorem intCast_emod (x : Int) : ((x % p : Int) : α) = (x : α) := by
rw [intCast_ext_iff p, Int.emod_emod]
@@ -534,6 +494,8 @@ end Ring
end IsCharP
open AddCommGroup
theorem no_int_zero_divisors {α : Type u} [IntModule α] [NoNatZeroDivisors α] {k : Int} {a : α}
: k 0 k * a = 0 a = 0 := by
match k with
@@ -541,15 +503,15 @@ theorem no_int_zero_divisors {α : Type u} [IntModule α] [NoNatZeroDivisors α]
simp only [ne_eq, Int.natCast_eq_zero]
intro h₁ h₂
replace h₁ : k 0 := by intro h; simp [h] at h₁
rw [IntModule.hmul_nat] at h₂
rw [IntModule.zsmul_natCast_eq_nsmul] at h₂
exact NoNatZeroDivisors.eq_zero_of_mul_eq_zero h₁ h₂
| -(k+1 : Nat) =>
rw [IntModule.neg_hmul]
rw [IntModule.neg_zsmul]
intro _ h
replace h := congrArg (-·) h
dsimp only at h
rw [IntModule.neg_neg, IntModule.neg_zero] at h
rw [IntModule.hmul_nat] at h
rw [neg_neg, neg_zero] at h
rw [IntModule.zsmul_natCast_eq_nsmul] at h
exact NoNatZeroDivisors.eq_zero_of_mul_eq_zero (Nat.succ_ne_zero _) h
end Lean.Grind

Some files were not shown because too many files have changed in this diff Show More