import Spa.Lattice
import Mathlib.Data.Finset.Lattice.Basic
import Mathlib.Data.Fintype.Lattice
import Mathlib.Data.Fintype.Card

/-! # Power Sets of Finite Type

For a `Fintype α`, `Finset α` is the power-set lattice: `⊔` is union, `⊓` is
intersection, `⊥ = ∅`, `⊤ = univ`. This lattice also has a finite height.

The `Finset α` representation s isomorphic to `Fin α → Bool`, but far more
efficient because it avoids building up stacks of layered closures. -/

namespace Spa

variable {α : Type*} [Fintype α] [DecidableEq α]

omit [Fintype α] [DecidableEq α] in
private lemma finset_card_strictMono : StrictMono (Finset.card : Finset α → ℕ) :=
  fun _ _ h => Finset.card_lt_card h

omit [DecidableEq α] in
/-- A strictly increasing chain of finsets grows its cardinality by at least one
    each step, and cardinality is capped by `Fintype.card α`. -/
lemma finset_boundedChains : BoundedChains (Finset α) (Fintype.card α) := fun c => by
  have h := LTSeries.head_add_length_le_nat (c.map Finset.card finset_card_strictMono)
  rw [LTSeries.head_map, LTSeries.last_map, LTSeries.map_length] at h
  have h2 : c.last.card ≤ Fintype.card α := Finset.card_le_univ _
  omega

instance instFiniteHeightFinset : FiniteHeightLattice (Finset α) where
  toLattice := inferInstance
  toOrderBot := inferInstance
  toOrderTop := inferInstance
  height := Fintype.card α
  chains_bounded := finset_boundedChains

end Spa
