@@ -105,51 +105,44 @@ lemma List.range_succ_eq_map' {n nn n' : ℕ} (pn : NormNum.IsNat n nn) (pn' : n
105
105
List.range n = 0 :: List.map Nat.succ (List.range n') := by
106
106
rw [pn.out, Nat.cast_id, pn', List.range_succ_eq_map]
107
107
108
+ set_option linter.unusedVariables false in
108
109
/-- Either show the expression `s : Q(List α)` is Nil, or remove one element from it.
109
110
110
111
Fails if we cannot determine which of the alternatives apply to the expression.
111
112
-/
112
- partial def List.proveNilOrCons {α : Q(Type u)} :
113
- (s : Q(List $α)) → MetaM (List.ProveNilOrConsResult s) :=
114
- fun s =>
113
+ partial def List.proveNilOrCons {α : Q(Type u)} (s : Q(List $α)) :
114
+ MetaM (List.ProveNilOrConsResult s) :=
115
115
s.withApp fun e a =>
116
116
match (e, e.constName, a) with
117
- | (_, `EmptyCollection.EmptyCollection, _) => pure (.nil (q(rfl) : Q((∅ : List $α) = [])))
118
- | (_, `List.nil, _) => pure (.nil (q(rfl) : Q(([] : List $α) = [])))
119
- | (_, `List.cons, #[_, a, s']) => pure (.cons a s' (q(rfl) : Q($s = $s)))
120
- | (_, `List.range, #[(n : Q(ℕ))]) => do
121
- let instAMO_nat : Q(AddMonoidWithOne ℕ) := q(AddCommMonoidWithOne.toAddMonoidWithOne)
122
- let ⟨nn, pn⟩ ← NormNum.deriveNat n
117
+ | (_, ``EmptyCollection.emptyCollection, _) => haveI : $s =Q {} := ⟨⟩; pure (.nil q(.refl []))
118
+ | (_, ``List.nil, _) => haveI : $s =Q [] := ⟨⟩; pure (.nil q(rfl))
119
+ | (_, ``List.cons, #[_, (a : Q($α)), (s' : Q(List $α))]) =>
120
+ haveI : $s =Q $a :: $s' := ⟨⟩; pure (.cons a s' q(rfl))
121
+ | (_, ``List.range, #[(n : Q(ℕ))]) =>
122
+ have s : Q(List ℕ) := s; .uncheckedCast _ _ <$> show MetaM (ProveNilOrConsResult s) from do
123
+ let ⟨nn, pn⟩ ← NormNum.deriveNat n _
124
+ haveI' : $s =Q .range $n := ⟨⟩
123
125
let nnL := nn.natLit!
124
126
if nnL = 0 then
125
- let pn : Q(@NormNum.IsNat _ _ $n 0 ) := pn
126
- return .nil ( q(List.range_zero' $pn) : Q(List.range $n = []) )
127
+ haveI' : $nn =Q 0 := ⟨⟩
128
+ return .nil q(List.range_zero' $pn)
127
129
else
128
130
have n' : Q(ℕ) := mkRawNatLit (nnL - 1 )
129
- let pn' : Q($nn = Nat.succ $n') := (q(Eq.refl $nn) : Expr)
130
- return (List.ProveNilOrConsResult.cons
131
- q(0 )
132
- q(List.map Nat.succ (List.range $n'))
133
- q(List.range_succ_eq_map' $pn $pn')).uncheckedCast (q(List.range ($n)) : Q(List ℕ)) s
134
- | (_, `List.finRange, #[(n : Q(ℕ))]) => do
135
- match ← Nat.unifyZeroOrSucc n with -- We want definitional equality on `n`.
136
- | .zero _pf => do
137
- pure (.nil (q(List.finRange_zero) : Q(List.finRange 0 = [])))
138
- | .succ n' _pf => pure <| ((List.ProveNilOrConsResult.cons
139
- q(0 : Fin (Nat.succ $n'))
140
- (q(List.map Fin.succ (List.finRange $n')))
141
- (q(List.finRange_succ_eq_map $n'))).uncheckedCast
142
- (q(List.finRange (Nat.succ $n')) : Q(List (Fin (Nat.succ $n'))))
143
- s)
144
- | (.const `List.map [v, _], _, #[β, _, f, xxs]) => do
145
- have β : Q(Type v) := β
146
- have f : Q($β → $α) := f
147
- have xxs : Q(List $β) := xxs
148
- match ← List.proveNilOrCons xxs with
149
- | .nil pf => pure <| (.nil
150
- (q($pf ▸ List.map_nil) : Q(List.map $f $xxs = [])))
151
- | .cons x xs pf => pure <| (.cons q($f $x) q(List.map $f $xs)
152
- (q($pf ▸ List.map_cons $f $x $xs) : Q(List.map $f $xxs = $f $x :: List.map $f $xs)))
131
+ have : $nn =Q .succ $n' := ⟨⟩
132
+ return .cons _ _ q(List.range_succ_eq_map' $pn (.refl $nn))
133
+ | (_, ``List.finRange, #[(n : Q(ℕ))]) =>
134
+ have s : Q(List (Fin $n)) := s
135
+ .uncheckedCast _ _ <$> show MetaM (ProveNilOrConsResult s) from do
136
+ haveI' : $s =Q .finRange $n := ⟨⟩
137
+ return match ← Nat.unifyZeroOrSucc n with -- We want definitional equality on `n`.
138
+ | .zero _pf => .nil q(List.finRange_zero)
139
+ | .succ n' _pf => .cons _ _ q(List.finRange_succ_eq_map $n')
140
+ | (.const ``List.map [v, _], _, #[(β : Q(Type v)), _, (f : Q($β → $α)), (xxs : Q(List $β))]) => do
141
+ haveI' : $s =Q ($xxs).map $f := ⟨⟩
142
+ return match ← List.proveNilOrCons xxs with
143
+ | .nil pf => .nil q(($pf ▸ List.map_nil : List.map _ _ = _))
144
+ | .cons x xs pf => .cons q($f $x) q(($xs).map $f)
145
+ q(($pf ▸ List.map_cons $f $x $xs : List.map _ _ = _))
153
146
| (_, fn, args) =>
154
147
throwError "List.proveNilOrCons: unsupported List expression {s} ({fn}, {args})"
155
148
@@ -194,33 +187,31 @@ lemma Multiset.range_succ' {n nn n' : ℕ} (pn : NormNum.IsNat n nn) (pn' : nn =
194
187
195
188
Fails if we cannot determine which of the alternatives apply to the expression.
196
189
-/
197
- partial def Multiset.proveZeroOrCons {α : Q(Type u)} :
198
- (s : Q(Multiset $α)) → MetaM (Multiset.ProveZeroOrConsResult s) :=
199
- fun s =>
200
- match Expr.getAppFnArgs s with
201
- | (`EmptyCollection.EmptyCollection, _) => pure (.zero (q(rfl) : Q((∅ : Multiset $α) = 0 )))
202
- | (`Zero.zero, _) => pure (.zero (q(rfl) : Q((0 : Multiset $α) = 0 )))
203
- | (`Multiset.cons, #[_, a, s']) => pure (.cons a s' (q(rfl) : Q($s = $s)))
204
- | (`Multiset.ofList, #[_, (val : Q(List $α))]) => do
205
- match ← List.proveNilOrCons val with
206
- | .nil pf => pure <| .zero (q($pf ▸ Multiset.coe_nil) : Q(($val : Multiset $α) = 0 ))
207
- | .cons a s' pf => do
208
- return (.cons a q($s')
209
- (q($pf ▸ Multiset.cons_coe $a $s') : Q(↑$val = Multiset.cons $a $s')))
210
- | (`Multiset.range, #[(n : Q(ℕ))]) => do
211
- let instAMO_nat : Q(AddMonoidWithOne ℕ) := q(AddCommMonoidWithOne.toAddMonoidWithOne)
212
- let ⟨nn, pn⟩ ← NormNum.deriveNat n
190
+ partial def Multiset.proveZeroOrCons {α : Q(Type u)} (s : Q(Multiset $α)) :
191
+ MetaM (Multiset.ProveZeroOrConsResult s) :=
192
+ match s.getAppFnArgs with
193
+ | (``EmptyCollection.emptyCollection, _) => haveI : $s =Q {} := ⟨⟩; pure (.zero q(rfl))
194
+ | (``Zero.zero, _) => haveI : $s =Q 0 := ⟨⟩; pure (.zero q(rfl))
195
+ | (``Multiset.cons, #[_, (a : Q($α)), (s' : Q(Multiset $α))]) =>
196
+ haveI : $s =Q .cons $a $s' := ⟨⟩
197
+ pure (.cons a s' q(rfl))
198
+ | (``Multiset.ofList, #[_, (val : Q(List $α))]) => do
199
+ haveI : $s =Q .ofList $val := ⟨⟩
200
+ return match ← List.proveNilOrCons val with
201
+ | .nil pf => .zero q($pf ▸ Multiset.coe_nil : Multiset.ofList _ = _)
202
+ | .cons a s' pf => .cons a q($s') q($pf ▸ Multiset.cons_coe $a $s' : Multiset.ofList _ = _)
203
+ | (``Multiset.range, #[(n : Q(ℕ))]) => do
204
+ have s : Q(Multiset ℕ) := s; .uncheckedCast _ _ <$> show MetaM (ProveZeroOrConsResult s) from do
205
+ let ⟨nn, pn⟩ ← NormNum.deriveNat n _
206
+ haveI' : $s =Q .range $n := ⟨⟩
213
207
let nnL := nn.natLit!
214
208
if nnL = 0 then
215
- let pn : Q(@NormNum.IsNat _ _ $n 0 ) := pn
216
- return .zero ( q(Multiset.range_zero' $pn) : Q(Multiset.range $n = 0 ) )
209
+ haveI' : $nn =Q 0 := ⟨⟩
210
+ return .zero q(Multiset.range_zero' $pn)
217
211
else
218
212
have n' : Q(ℕ) := mkRawNatLit (nnL - 1 )
219
- let pn' : Q($nn = Nat.succ $n') := (q(Eq.refl $nn) : Expr)
220
- return (Multiset.ProveZeroOrConsResult.cons
221
- n'
222
- q(Multiset.range $n')
223
- q(Multiset.range_succ' $pn $pn')).uncheckedCast (q(Multiset.range ($n)) : Q(Multiset ℕ)) s
213
+ haveI' : $nn =Q ($n').succ := ⟨⟩
214
+ return .cons _ _ q(Multiset.range_succ' $pn rfl)
224
215
| (fn, args) =>
225
216
throwError "Multiset.proveZeroOrCons: unsupported multiset expression {s} ({fn}, {args})"
226
217
@@ -270,13 +261,14 @@ lemma Finset.univ_eq_elems {α : Type _} [Fintype α] (elems : Finset α)
270
261
271
262
Fails if we cannot determine which of the alternatives apply to the expression.
272
263
-/
273
- partial def Finset.proveEmptyOrCons {α : Q(Type u)} :
274
- (s : Q(Finset $α)) → MetaM (Finset.ProveEmptyOrConsResult s) :=
275
- fun s =>
276
- match Expr.getAppFnArgs s with
277
- | (`EmptyCollection.emptyCollection, _) => pure (.empty (q(rfl) : Q($s = $s)))
278
- | (`Finset.cons, #[_, a, s', h]) => pure (.cons a s' h (q(rfl) : Q($s = $s)))
279
- | (`Finset.mk, #[_, (val : Q(Multiset $α)), (nd : Q(Multiset.Nodup $val))]) => do
264
+ partial def Finset.proveEmptyOrCons {α : Q(Type u)} (s : Q(Finset $α)) :
265
+ MetaM (ProveEmptyOrConsResult s) :=
266
+ match s.getAppFnArgs with
267
+ | (``EmptyCollection.emptyCollection, _) => haveI : $s =Q {} := ⟨⟩; pure (.empty q(rfl))
268
+ | (``Finset.cons, #[_, (a : Q($α)), (s' : Q(Finset $α)), (h : Q(¬ $a ∈ $s'))]) =>
269
+ haveI : $s =Q .cons $a $s' $h := ⟨⟩
270
+ pure (.cons a s' h q(.refl $s))
271
+ | (``Finset.mk, #[_, (val : Q(Multiset $α)), (nd : Q(Multiset.Nodup $val))]) => do
280
272
match ← Multiset.proveZeroOrCons val with
281
273
| .zero pf => pure <| .empty (q($pf ▸ Finset.mk_zero) : Q(Finset.mk $val $nd = ∅))
282
274
| .cons a s' pf => do
@@ -285,29 +277,24 @@ partial def Finset.proveEmptyOrCons {α : Q(Type u)} :
285
277
let h' : Q($a ∉ $s') := q((Multiset.nodup_cons.mp $h).1 )
286
278
return (.cons a q(Finset.mk $s' $nd') h'
287
279
(q($pf ▸ Finset.mk_cons $h) : Q(Finset.mk $val $nd = Finset.cons $a ⟨$s', $nd'⟩ $h')))
288
- | (`Finset.range, #[(n : Q(ℕ))]) => do
289
- let instAMO_nat : Q(AddMonoidWithOne ℕ) := q(AddCommMonoidWithOne.toAddMonoidWithOne)
290
- let ⟨nn, pn⟩ ← NormNum.deriveNat n
280
+ | (``Finset.range, #[(n : Q(ℕ))]) =>
281
+ have s : Q(Finset ℕ) := s; .uncheckedCast _ _ <$> show MetaM (ProveEmptyOrConsResult s) from do
282
+ let ⟨nn, pn⟩ ← NormNum.deriveNat n _
283
+ haveI' : $s =Q .range $n := ⟨⟩
291
284
let nnL := nn.natLit!
292
285
if nnL = 0 then
293
- let pn : Q(@NormNum.IsNat _ _ $n 0 ) := pn
294
- return .empty ( q(Finset.range_zero' $pn) : Q(Finset.range $n = {}) )
286
+ haveI : $nn =Q 0 := ⟨⟩
287
+ return .empty q(Finset.range_zero' $pn)
295
288
else
296
289
have n' : Q(ℕ) := mkRawNatLit (nnL - 1 )
297
- let pn' : Q($nn = Nat.succ $n') := (q(Eq.refl $nn) : Expr)
298
- return (Finset.ProveEmptyOrConsResult.cons
299
- n'
300
- (q(Finset.range $n'))
301
- (q(@Finset.not_mem_range_self $n'))
302
- (q(Finset.range_succ' $pn $pn'))).uncheckedCast
303
- (q(Finset.range $n) : Q(Finset ℕ))
304
- s
305
- | (`Finset.univ, #[_, instFT]) => do
306
- match Expr.getAppFnArgs (← whnfI instFT) with
307
- | (`Fintype.mk, #[_, (elems : Q(Finset $α)), (complete : Q(∀ x : $α, x ∈ $elems))]) => do
308
- have _instFT : Q(Fintype $α) := instFT
290
+ haveI' : $nn =Q ($n').succ := ⟨⟩
291
+ return .cons n' _ _ q(Finset.range_succ' $pn (.refl $nn))
292
+ | (``Finset.univ, #[_, (instFT : Q(Fintype $α))]) => do
293
+ haveI' : $s =Q .univ := ⟨⟩
294
+ match (← whnfI instFT).getAppFnArgs with
295
+ | (``Fintype.mk, #[_, (elems : Q(Finset $α)), (complete : Q(∀ x : $α, x ∈ $elems))]) => do
309
296
let res ← Finset.proveEmptyOrCons elems
310
- pure <| res.eq_trans ( q(Finset.univ_eq_elems $elems $complete) : Q(Finset.univ = $elems) )
297
+ pure <| res.eq_trans q(Finset.univ_eq_elems $elems $complete)
311
298
| e =>
312
299
throwError "Finset.proveEmptyOrCons: could not determine elements of Fintype instance {e}"
313
300
| (fn, args) =>
@@ -374,7 +361,7 @@ partial def evalFinsetProd : NormNumExt where eval {u β} e := do
374
361
have α : Q(Type v) := α
375
362
have s : Q(Finset $α) := s
376
363
have f : Q($α → $β) := f
377
- let instCS ← synthInstanceQ (q( CommSemiring $β) : Q( Type u) ) <|>
364
+ let instCS : Q( CommSemiring $β) ← synthInstanceQ q(CommSemiring $β ) <|>
378
365
throwError "not a commutative semiring: {β}"
379
366
let instS : Q(Semiring $β) := q(CommSemiring.toSemiring)
380
367
-- Have to construct this expression manually, `q(1)` doesn't parse correctly:
@@ -384,7 +371,7 @@ partial def evalFinsetProd : NormNumExt where eval {u β} e := do
384
371
385
372
evalFinsetBigop q(Finset.prod) f res_empty (fun {a s' h} res_fa res_prod_s' ↦ do
386
373
let fa : Q($β) := Expr.app f a
387
- let res : Result _ ← evalMul.core q($fa * Finset.prod $s' $f) q((· * ·) ) _ _ instS res_fa
374
+ let res ← evalMul.core q($fa * Finset.prod $s' $f) q(HMul.hMul ) _ _ instS res_fa
388
375
res_prod_s'
389
376
let eq : Q(Finset.prod (Finset.cons $a $s' $h) $f = $fa * Finset.prod $s' $f) :=
390
377
q(Finset.prod_cons $h)
@@ -403,15 +390,15 @@ partial def evalFinsetSum : NormNumExt where eval {u β} e := do
403
390
have α : Q(Type v) := α
404
391
have s : Q(Finset $α) := s
405
392
have f : Q($α → $β) := f
406
- let instCS ← synthInstanceQ (q( CommSemiring $β) : Q( Type u) ) <|>
393
+ let instCS : Q( CommSemiring $β) ← synthInstanceQ q(CommSemiring $β ) <|>
407
394
throwError "not a commutative semiring: {β}"
408
- let n : Q(ℕ) := q( 0 )
395
+ let n : Q(ℕ) := mkRawNatLit 0
409
396
let pf : Q(IsNat (Finset.sum ∅ $f) $n) := q(@Finset.sum_empty $β $α $instCS $f)
410
397
let res_empty := Result.isNat _ n pf
411
398
412
399
evalFinsetBigop q(Finset.sum) f res_empty (fun {a s' h} res_fa res_sum_s' ↦ do
413
400
let fa : Q($β) := Expr.app f a
414
- let res : Result _ ← evalAdd.core q($fa + Finset.sum $s' $f) q((· + ·) ) _ _ res_fa res_sum_s'
401
+ let res ← evalAdd.core q($fa + Finset.sum $s' $f) q(HAdd.hAdd ) _ _ res_fa res_sum_s'
415
402
let eq : Q(Finset.sum (Finset.cons $a $s' $h) $f = $fa + Finset.sum $s' $f) :=
416
403
q(Finset.sum_cons $h)
417
404
pure <| res.eq_trans eq)
0 commit comments