namespace BidirTT inductive Level where | zero : Level | succ : Level → Level | max : Level → Level → Level deriving Repr, Inhabited, BEq, DecidableEq def Level.ofNat : Nat → Level | 0 => .zero | n + 1 => .succ (Level.ofNat n) instance (n : Nat) : OfNat Level n where ofNat := Level.ofNat n partial def Level.eval : Level → Nat | .zero => 0 | .succ l => l.eval + 1 | .max l r => Nat.max l.eval r.eval def Level.normalise (l : Level) : Level := .ofNat l.eval def Level.succ' (l : Level) : Level := .normalise (.succ l) def Level.max' (l r : Level) : Level := .normalise (.max l r) def Level.pretty (l : Level) : String := s!"{l.eval}" abbrev LevelConstraint := Level × Level def solveLevelConstraints (constraints : List LevelConstraint) : Except String Unit := do match constraints.find? fun (lhs, rhs) => lhs.eval > rhs.eval with | some (lhs, rhs) => throw s!"unsatisfiable level constraint {lhs.pretty} <= {rhs.pretty}" | none => pure () def Level.leq (lhs rhs : Level) : Except String Bool := do match solveLevelConstraints [(lhs, rhs)] with | Except.ok _ => pure true | Except.error _ => pure false def Level.eqv (lhs rhs : Level) : Except String Bool := do match solveLevelConstraints [(lhs, rhs), (rhs, lhs)] with | Except.ok _ => pure true | Except.error _ => pure false end BidirTT