import Spa.Lattice.Prod import Spa.Lattice.Unit 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} instance instLattice [Lattice A] [Lattice B] : ∀ k, Lattice (IterProd A B k) | 0 => inferInstanceAs (Lattice B) | k + 1 => @Prod.instLattice A (IterProd A B k) _ (instLattice k) instance instDecidableEq [DecidableEq A] [DecidableEq B] : ∀ k, DecidableEq (IterProd A B k) | 0 => inferInstanceAs (DecidableEq B) | k + 1 => @instDecidableEqProd A (IterProd A B k) _ (instDecidableEq k) def build (a : A) (b : B) : (k : ℕ) → IterProd A B k | 0 => b | k + 1 => (a, build a b k) variable [Lattice A] [Lattice B] 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) _ (instLattice k) _ (fixedHeight k) instance instFiniteHeight [FiniteHeightLattice A] [FiniteHeightLattice B] (k : ℕ) : FiniteHeightLattice (IterProd A B k) := fixedHeight k theorem bot_fixedHeight [FiniteHeightLattice A] [FiniteHeightLattice B] : ∀ k, (fixedHeight (A := A) (B := B) k).bot = build (⊥ : A) (⊥ : B) k | 0 => rfl | k + 1 => by show ((⊥ : A), (fixedHeight (A := A) (B := B) k).bot) = ((⊥ : A), build (⊥ : A) (⊥ : B) k) rw [bot_fixedHeight k] end IterProd end Spa