Skip to content

Commit dad08fa

Browse files
committed
feat: PiFin.mkLiteralQ and Matrix.mkLiteralQ (#24101)
This defines some new functions to match the `Qq.mkSetLiteralQ` from #23025. The commented `pexpr` function is really just the syntax quotation `` `(![$xs,*]) ``, so it is no longer worth keeping around. This deliberately uses `Fin n → Q($α)` instead of `Vector Q($α) n` as the former saves needing to allocate an auxiliary array, and the latter still can be used by passing in `v.get : Fin n → Q($α)`. This also cleans up and adds some related tests. Co-authored-by: Eric Wieser <efw@google.com>
1 parent 3553305 commit dad08fa

File tree

4 files changed

+49
-20
lines changed

4 files changed

+49
-20
lines changed

Mathlib/Data/Fin/VecNotation.lean

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -252,26 +252,25 @@ theorem cons_val_fin_one (x : α) (u : Fin 0 → α) : ∀ (i : Fin 1), vecCons
252252
theorem cons_fin_one (x : α) (u : Fin 0 → α) : vecCons x u = fun _ => x :=
253253
funext (cons_val_fin_one x u)
254254

255+
open Lean Qq in
256+
/-- `mkVecLiteralQ ![x, y, z]` produces the term `q(![$x, $y, $z])`. -/
257+
def _root_.PiFin.mkLiteralQ {u : Level} {α : Q(Type u)} {n : ℕ} (elems : Fin n → Q($α)) :
258+
Q(Fin $n → $α) :=
259+
loop 0 (Nat.zero_le _) q(vecEmpty)
260+
where
261+
loop (i : ℕ) (hi : i ≤ n) (rest : Q(Fin $i → $α)) : let i' : Nat := i + 1; Q(Fin $(i') → $α) :=
262+
if h : i < n then
263+
loop (i + 1) h q(vecCons $(elems (Fin.rev ⟨i, h⟩)) $rest)
264+
else
265+
rest
266+
attribute [nolint docBlame] _root_.PiFin.mkLiteralQ.loop
267+
255268
open Lean Qq in
256269
protected instance _root_.PiFin.toExpr [ToLevel.{u}] [ToExpr α] (n : ℕ) : ToExpr (Fin n → α) :=
257270
have lu := toLevel.{u}
258271
have eα : Q(Type $lu) := toTypeExpr α
259-
have toTypeExpr := q(Fin $n → $eα)
260-
match n with
261-
| 0 => { toTypeExpr, toExpr := fun _ => q(@vecEmpty $eα) }
262-
| n + 1 =>
263-
{ toTypeExpr, toExpr := fun v =>
264-
have := PiFin.toExpr n
265-
have eh : Q($eα) := toExpr (vecHead v)
266-
have et : Q(Fin $n → $eα) := toExpr (vecTail v)
267-
q(vecCons $eh $et) }
268-
269-
-- TODO(eric-wieser): the next decl is commented out.
270-
271-
-- /-- Convert a vector of pexprs to the pexpr constructing that vector. -/
272-
-- unsafe def _root_.pi_fin.to_pexpr : ∀ {n}, (Fin n → pexpr) → pexpr
273-
-- | 0, v => ``(![])
274-
-- | n + 1, v => ``(vecCons $(v 0) $(_root_.pi_fin.to_pexpr <| vecTail v))
272+
let toTypeExpr := q(Fin $n → $eα)
273+
{ toTypeExpr, toExpr v := PiFin.mkLiteralQ fun i => show Q($eα) from toExpr (v i) }
275274

276275
/-! ### `bit0` and `bit1` indices
277276
The following definitions and `simp` lemmas are used to allow

Mathlib/Data/Matrix/Notation.lean

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ section toExpr
4949

5050
open Lean Qq
5151

52+
open Qq in
53+
/-- `Matrix.mkLiteralQ !![a, b; c, d]` produces the term `q(!![$a, $b; $c, $d])`. -/
54+
def mkLiteralQ {u : Level} {α : Q(Type u)} {m n : Nat} (elems : Matrix (Fin m) (Fin n) Q($α)) :
55+
Q(Matrix (Fin $m) (Fin $n) $α) :=
56+
let elems := PiFin.mkLiteralQ (α := q(Fin $n → $α)) fun i => PiFin.mkLiteralQ fun j => elems i j
57+
q(Matrix.of $elems)
58+
5259
/-- Matrices can be reflected whenever their entries can. We insert a `Matrix.of` to
5360
prevent immediate decay to a function. -/
5461
protected instance toExpr [ToLevel.{u}] [ToLevel.{uₘ}] [ToLevel.{uₙ}]

MathlibTest/matrix.lean

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,13 @@ def mkMatrix (rows : Array (Array Term)) : Term := Unhygienic.run `(!![$[$[$rows
5757
def mkColumnVector (elems : Array Term) : Term := Unhygienic.run `(!![$[$elems];*])
5858

5959
-- Check that the `!![$[$[$rows],*];*]` case can deal with empty arrays even though it uses sepBy1
60-
run_cmd liftTermElabM do
60+
run_elab do
6161
let e ← Term.elabTerm (mkMatrix #[]) q(Matrix (Fin 0) (Fin 0) Nat)
6262
Term.synthesizeSyntheticMVarsUsingDefault
6363
let e ← instantiateMVars e
6464
guard <| e == q(!![] : Matrix (Fin 0) (Fin 0) Nat)
6565

66+
run_elab do
6667
let e ← Term.elabTerm (mkColumnVector #[]) q(Matrix (Fin 0) (Fin 0) Nat)
6768
Term.synthesizeSyntheticMVarsUsingDefault
6869
let e ← instantiateMVars e
@@ -76,6 +77,22 @@ end safety
7677
#guard !![1,2;3,4;] = of ![![1,2], ![3,4]]
7778
#guard !![1,2,;3,4,] = of ![![1,2], ![3,4]]
7879

80+
section to_expr
81+
82+
open Lean Meta
83+
84+
/-- info: !![1 + 1, 1 + 2; 2 + 1, 2 + 2] : Matrix (Fin 2) (Fin 2) ℕ -/
85+
#guard_msgs in
86+
#check by_elab return Matrix.mkLiteralQ !![q(1 + 1), q(1 + 2); q(2 + 1), q(2 + 2)]
87+
88+
run_elab do
89+
let x := !![1, 2; 3, 4]
90+
guard (← withReducible <| isDefEq (toExpr x) q(!![1, 2; 3, 4]))
91+
92+
end to_expr
93+
94+
section delaborators
95+
7996
/-- info: !![0, 1, 2; 3, 4, 5] : Matrix (Fin 2) (Fin 3) ℕ -/
8097
#guard_msgs in #check (!![0, 1, 2; 3, 4, 5] : Matrix (Fin 2) (Fin 3) ℕ)
8198

@@ -91,6 +108,8 @@ end safety
91108
/-- info: !![] : Matrix (Fin 0) (Fin 0) ℕ -/
92109
#guard_msgs in #check (!![] : Matrix (Fin 0) (Fin 0) ℕ)
93110

111+
end delaborators
112+
94113
example {a a' b b' c c' d d' : α} :
95114
!![a, b; c, d] + !![a', b'; c', d'] = !![a + a', b + b'; c + c', d + d'] := by
96115
simp

MathlibTest/vec_notation.lean

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,22 @@ open Qq
1111
set_option linter.style.setOption false in
1212
set_option pp.unicode.fun false
1313

14+
/-- info: ![1, 1 + 1, 1 + 1 + 1] : Fin (Nat.succ 2) → ℤ -/
15+
#guard_msgs in
16+
#check by_elab return PiFin.mkLiteralQ ![q(1 : ℤ), q(1 + 1), q(1 + 1 + 1)]
17+
1418
/-! These tests are testing `PiFin.toExpr` and fail with
1519
`local attribute [-instance] PiFin.toExpr` -/
1620

17-
run_cmd Elab.Command.liftTermElabM do
21+
run_elab do
1822
let x : Fin 0 → ℕ := ![]
1923
guard (← isDefEq (toExpr x) q((![] : Fin 0 → ℕ)))
2024

21-
run_cmd Elab.Command.liftTermElabM do
25+
run_elab do
2226
let x := ![1, 2, 3]
2327
guard (← isDefEq (toExpr x) q(![1, 2, 3]))
2428

25-
run_cmd Elab.Command.liftTermElabM do
29+
run_elab do
2630
let x := ![![1, 2], ![3, 4]]
2731
guard (← isDefEq (toExpr x) q(![![1, 2], ![3, 4]]))
2832

0 commit comments

Comments
 (0)