Zulip Chat Archive

Stream: new members

Topic: Equality problems when extending binary operation to n-ary


Cosmo Viola (May 23 2025 at 07:53):

I'm working with a binary operation on structures that carry both a type and functons with that type as a domain. I'm trying to extend that binary operation to an n-ary operation, but I'm running into dependent type problems when trying to calculate closed forms for the fields of the resulting structure. Here's a minimized example demonstrating the problem:

import Mathlib.Data.Fintype.Basic

structure ex where
  σ : Type
  f : σ  Nat

def prodEx (s1 s2 : ex) : ex where
  σ := s1.σ × s2.σ
  f := fun (σ1, σ2) => s1.f σ1 + s2.f σ2

def prodNEx {n : Nat} (tup : Fin n  ex) : ex :=
  match n with
  | 0 => {σ := PUnit, f := fun _ => 0}
  | 1 => (tup 0)
  | _ + 2 => prodEx (tup 0) (prodNEx (Fin.tail tup))

def prodNTypes {n : Nat} (XArr : Fin n  Type) :=
  match n with
  | 0 => PUnit
  | 1 => XArr 0
  | _ + 2 => (XArr 0) × (prodNTypes (Fin.tail XArr))

theorem prodNExSigma {n : Nat} (tup : Fin (n + 1)  ex) :
    (prodNEx tup).σ = prodNTypes (fun i => (tup i).σ) := by {
  induction n
  case zero =>
    rfl
  case succ n h =>
    simp [prodNEx, prodNTypes, prodEx]
    rw [h]
    aesop
}

def prodNFs {n : Nat} (tupσ : Fin n  Type) (tupF : (i : Fin n)  (tupσ i)  Nat) : (prodNTypes tupσ)  Nat:=
  match n with
  | 0 => fun (_ : PUnit) => 0
  | 1 => (tupF 0)
  | _ + 2 => fun (σ1, σ2) => (tupF 0 σ1) + (prodNFs (Fin.tail tupσ) (Fin.tail tupF) σ2)

theorem prodNExF {n : Nat} (tup : Fin (n + 1)  ex) :
    (prodNEx tup).f = fun σ => prodNFs (fun i => (tup i).σ) (fun i => (tup i).f) (prodNExSigma tup  σ) := by {
  induction n
  case zero =>
    aesop
  case succ =>
    simp [prodNFs]
    sorry
}

The σ field of prodNEx tup is tup 0 × (tup 1 × ...). As far as I can tell, this specific n-ary product isn't well supported in mathlib, so I define prodNTypes, which translates a tuple into one. This allows me to prove a theorem calculating (prodNEx tup).σ. However, to calculate (prodNEx tup).f, we need to translate an element of type (prodNEx tup).σ to type prodNTypes (fun i => (tup i).σ). As a result, in the succ case of prodNExF, we end up matching on an equality proof, and I'm unsure of how to make progress. I know that in general working with equalities of types is painful. Is there a good way to prove these goals in Lean? I know in many cases it's recommended to use isomorphisms instead of equalities, such as with Fin.cast. Should I be constructing an isomorphism between these types and using that instead of the equality I prove?

Eric Paul (May 24 2025 at 07:02):

This might not be helpful, but using split lets you make progress on the match. Things still do seem difficult to work with.

theorem prodNExF {n : Nat} (tup : Fin (n + 1)  ex) :
    (prodNEx tup).f = fun σ => prodNFs (fun i => (tup i).σ) (fun i => (tup i).f) (prodNExSigma tup  σ) := by
  induction n
  case zero =>
    aesop
  case succ n ih =>
    simp [prodNFs]
    ext z
    split
    rename_i a b c d
    simp [prodNEx, prodEx, ih]
    sorry

Last updated: Dec 20 2025 at 21:32 UTC