/- Port of `Lattice/IterProd.agda`: the `k`-fold product `A × (A × ⋯ × B)`. With propositional equality and typeclasses, the Agda `Everything` record (which threaded the lattice operations and the conditional fixed-height proof through one recursion, so that the operations built by separate recursions would agree) is no longer needed: the `Lattice` instance is one recursive definition, and the fixed-height structure is another recursion over it. Correspondence: IterProd ↦ Spa.IterProd build ↦ Spa.IterProd.build isLattice/lattice ↦ instance Spa.IterProd.instLattice fixedHeight, isFiniteHeightLattice, finiteHeightLattice ↦ Spa.IterProd.fixedHeight (+ instFiniteHeight instance) ⊥-built ↦ Spa.IterProd.bot_fixedHeight -/ import Spa.Lattice.Prod import Spa.Lattice.Unit namespace Spa universe u /-- Agda: `IterProd k = iterate k (A × ·) B`. (As in the Agda module, `A` and `B` are constrained to the same universe to keep the recursion simple.) -/ 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) /-- Agda: `build`. -/ 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