Zulip Chat Archive
Stream: new members
Topic: Matrix from dependent type `Vec n α`
Curious Joe (Dec 04 2024 at 14:01):
Hi all!
I am trying to construct a matrix based on a dependent type Vec n α
.
The matrix has type Vec n (Vec m α)
where n
and m
are decided at runtime.
I am trying to construct the matrix Vec n (Vec m α)
from a List (List α)
where for simplicity I set α := Nat
.
However, I am having trouble with this.
My code is the following:
abbrev Vec (n : Nat) (a : Type) := { ls : List a // ls.length = n }
abbrev Matrix (n m : Nat) (a : Type) := Vec n (Vec m a)
def test_mat (mat : List (List Nat)) :=
let m := mat[0]!.length
let d : List (Option (Vec m Nat)) := mat.map (fun row =>
let row_length := row.length
if h1 : row_length = m then
pure ⟨row, h1⟩
else
none
)
let df := d.filterMap id
let n := df.length
let mat : Matrix n m Nat := ⟨df, by decide⟩
mat
def output_testmat := test_mat [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
#eval output_testmat
At the let mat
line I get the following error:
▶ 15:39-15:45: error:
expected type must not contain free or meta variables
(List.filterMap id
(List.map (fun row => if h1 : row.length = mat[0]!.length then pure ⟨row, h1⟩ else none) mat)).length =
(List.filterMap id
(List.map (fun row => if h1 : row.length = mat[0]!.length then pure ⟨row, h1⟩ else none) mat)).length
Does anyone have any good tips on how to proceed with this?
I rather not use anything from mathlib
and instead construct the type for
myself.
Many thanks!
Henrik Böving (Dec 04 2024 at 14:04):
You could use something along the lines of
def test_mat (mat : List (List Nat)) : (n : Nat) × (m : Nat) × (Matrix n m Nat)
So you return the dimensions of the matrix that you build along with the matrix itself.
Curious Joe (Dec 04 2024 at 14:10):
Thanks a lot! That makes sense.
However, I still get the same error at the mat
line:
▶ expected type (45:3-46:14)
mat : List (List Nat)
m : Nat := mat[0]!.length
d : List (Option (Vec m Nat)) := List.map
(fun row =>
let row_length := row.length;
if h1 : row_length = m then pure ⟨row, h1⟩ else none)
mat
df : List (Vec m Nat) := List.filterMap id d
n : Nat := df.length
⊢ (n : Nat) × (m : Nat) × Matrix n m Nat
▶ 45:42-45:48: error:
expected type must not contain free or meta variables
(List.filterMap id
(List.map (fun row => if h1 : row.length = mat[0]!.length then pure ⟨row, h1⟩ else none) mat)).length =
(List.filterMap id
(List.map (fun row => if h1 : row.length = mat[0]!.length then pure ⟨row, h1⟩ else none) mat)).length
Curious Joe (Dec 04 2024 at 14:35):
Okay so I managed to construct a solution that is good enough for me although
it feels a bit hacky :D
I use a Monad transformer and a config where I hardcode the matrix dimensions
upfront.
The #eval output_testmat
yields output:
▶ 34:1-34:6: information:
Except.ok { n := 3, m := 3, fields := [[1, 2, 3], [4, 5, 6], [7, 8, 9]] }
Code:
abbrev Vec (n : Nat) (a : Type) := { ls : List a // ls.length = n }
abbrev Matrix (n m : Nat) (a : Type) := Vec n (Vec m a)
structure MatrixWrapper where
n : Nat
m : Nat
fields: Vec n (Vec m Nat)
deriving Repr
structure Config where
n : Nat
m : Nat
def test_mat (mat : List (List Nat)) : ReaderT Config (Except String)
MatrixWrapper := do
let conf ← read
let n := conf.n
let m := conf.m
let p1 : List (Option (Vec m Nat)) := mat.map (
fun row =>
if h1 : row.length = conf.m then
pure ⟨row, h1⟩
else
none
)
let p2 := p1.filterMap id
if h2 : p2.length = n then
let mat : Vec n (Vec m Nat) := ⟨p2, h2⟩
pure {n := n, m := m, fields := mat : MatrixWrapper}
else
throw "something"
def output_testmat := test_mat [[1, 2, 3], [4, 5, 6], [7, 8, 9]] {n := 3, m := 3}
#eval output_testmat
Last updated: May 02 2025 at 03:31 UTC