Finite-Index Signature Tuples (Fin n → σ i)

dependently-typed, index-based tuple representation, good for repreesenting fixed-arity, heterogeneously-typed structures.

namespace DMT1.Lecture.hetero.hetero

open Std

-- A heterogeneous n-tuple type: σ is a signature Fin n → Type
def Sig (n : Nat) := Fin n → Type
def Val (σ : Sig n) := ∀ i : Fin n, σ i

-- Collects Repr instances for a given signature
class BuildReprs {n : Nat} (σ : Sig n) where
  reprs : ∀ i : Fin n, Repr (σ i)

-- Pretty print each entry using its Repr instance
def toReprList {n : Nat} {σ : Sig n} [BuildReprs σ] (v : Val σ) : List String :=
  List.ofFn (fun i => Format.pretty ((BuildReprs.reprs i).reprPrec (v i) 0) 80)

def toPrettyString {n : Nat} {σ : Sig n} [BuildReprs σ] (v : Val σ) : String :=
  s!"[{String.intercalate ", " (toReprList v)}]"

-- Example signature and value
def sig3 : Sig 3
| 0 => Nat
| 1 => Bool
| 2 => String

def val3 : Val sig3
| 0 => (42 : Nat)
| 1 => true
| 2 => "hello"

instance : BuildReprs sig3 where
  reprs
  | 0 => inferInstanceAs (Repr Nat)
  | 1 => inferInstanceAs (Repr Bool)
  | 2 => inferInstanceAs (Repr String)


#eval toPrettyString val3 -- "[42, true, hello]"
  • Fixed-length, statically typed heterogeneity

  • statically typed, fixed arity tuples with per-index types

  • Fast index-based access (like arrays)

  • Dependent functions on each component

  • Suitable for modeling e.g. function signatures and argument packs, struct layouts, schemas

Compared to HList, this gives you:

  • Random access via Fin n rather than recursive pattern matching
  • Better performance and inference in many cases?
  • More natural fit for modeling arities of known size?
end DMT1.Lecture.hetero.hetero