The goal at the crucial step is
```
a : Array Nat
i : Fin ?m.27
⊢ ↑i < a.size
```
and after the `apply Fin.val_lt_of_le;` we have
```
a : Array Nat
i : Fin ?m.27
⊢ ?m.27 ≤ a.size
```
and now `apply Fin.val_lt_of_le` applies again, due to accidential
defeq. Adding `with_reducible` helps here.
fixes#5061
### Preliminary PRs:
- [x] #4597
- [x] #4599
- [x] #4600
- [x] #4602
- [x] #4603
- [x] #4604
- [x] #4605
- [x] #4607
- [x] #4627
- [x] #4629
### Quick overview over API/naming changes compared to `Lean.HashMap`
and `Batteries.HashMap`:
#### Lean
* `find?` -> `get?`/`getElem?`
* `find!` -> `get!`/`gtetElem!`
* `findD` -> `getD`
* `findEntry?` -> not implemented for now
* `insert'` -> `containsThenInsert` (order reversed in result)
* `insertIfNew` -> `getThenInsertIfNew?` (order reversed in result)
* `numBuckets` -> `Internal.numBuckets`
* `ofListWith` -> not implemented for now
* `Array.groupByKey` -> not implemented for now
* `merge` -> not implemented for now, but you can use `insertMany`
#### Batteries
* `modify` -> not implemented for now
* `mergeWith` -> not implemented for now
* `mergeWithM` -> not implemented for now
This makes changes to the `GetElem` class so that it does not lead to
unnecessary overhead in container like `RBMap`.
The changes are to:
1. Make `getElem?` and `getElem!` part of the `GetElem` class so they
can be overridden in instances.
2. Introduce a `LawfulGetElem` class that contains correctness theorems
for `getElem?` and `getElem!` using the original definitions.
3. Reorganize definitions (e.g, by moving `GetElem` out of
`Init.Prelude`) so that the `GetElem` changes are feasible.
4. Provide `LawfulGetElem` instances to complement all existing
`GetElem` instances in Lean core.
To reduce the size of the PR, this doesn't do the work of providing new
`GetElem` instances for `RBMap`, `HashMap` etc. That will be done in a
separate PR (#3688) that depends on this.
---------
Co-authored-by: Mac Malone <tydeu@hatpress.net>