import Spa.Lattice.Prod
import Spa.Lattice.Unit

/-!

# Iterated Products

Given two types $\alpha$ and $\beta$ and a number $n$, produces
an iterated product:

$$
\overbrace{\alpha \times \ldots \times \alpha}^{n\ \text{times}} × \beta
$$

This is mostly a stepping stone for isomorphisms. In
`Spa/Lattice/Prod.lean`, By decomposing types such as `Fin n → α` into
`IterProd α PUnit n`, we can automatically get a proof of their finite
height via `Spa.FiniteHeightLattice.transport`.

-/

namespace Spa

universe u

def IterProd (A B : Type u) : ℕ → Type u
  | 0 => B
  | k + 1 => A × IterProd A B k

namespace IterProd

variable {A B : Type u}

def fixedHeight [FiniteHeightLattice A] [FiniteHeightLattice B] :
    ∀ k, FiniteHeightLattice (IterProd A B k)
  | 0 => inferInstanceAs (FiniteHeightLattice B)
  | k + 1 => @Spa.prod A (IterProd A B k) _ (fixedHeight k)

instance finiteHeight [FiniteHeightLattice A] [FiniteHeightLattice B] (k : ℕ) :
    FiniteHeightLattice (IterProd A B k) := fixedHeight k

end IterProd

end Spa
