import Spa.Lattice.FiniteMap
import Spa.Lattice.AboveBelow

namespace Spa

class Showable (α : Type*) where
  show' : α → String

export Showable (show')

instance : Showable String := ⟨fun s => "\"" ++ s ++ "\""⟩

instance : Showable ℕ := ⟨toString⟩

instance : Showable ℤ := ⟨toString⟩

instance {n : ℕ} : Showable (Fin n) := ⟨fun i => toString i.val⟩

instance {α β : Type*} [Showable α] [Showable β] : Showable (α × β) :=
  ⟨fun p => "(" ++ show' p.1 ++ ", " ++ show' p.2 ++ ")"⟩

instance : Showable PUnit := ⟨fun _ => "()"⟩

instance {α : Type*} [Showable α] : Showable (AboveBelow α) :=
  ⟨fun
    | .bot => "⊥"
    | .top => "⊤"
    | .mk x => show' x⟩

instance {α β : Type*} {ks : List α} [Showable α] [Showable β] :
    Showable (FiniteMap α β ks) :=
  ⟨fun fm =>
    "{" ++ fm.val.foldr (fun p rest => show' p.1 ++ " ↦ " ++ show' p.2 ++ ", " ++ rest) ""
        ++ "}"⟩

end Spa
