Theory Interval

(*<*)
theory Interval
  imports "HOL-Library.Extended_Nat" "HOL-Library.Product_Lexorder"
begin
(*>*)

section ‹Intervals›

typedef  = "{(i :: nat, j :: enat). i  j}"
  by (intro exI[of _ "(0, )"]) auto

setup_lifting type_definition_ℐ

instantiation  :: equal begin
lift_definition equal_ℐ :: "    bool" is "(=)" .
instance by standard (transfer, auto)
end

instantiation  :: linorder begin
lift_definition less_eq_ℐ :: "    bool" is "(≤)" .
lift_definition less_ℐ :: "    bool" is "(<)" .
instance by standard (transfer, auto)+
end


lift_definition all ::  is "(0, )" by simp
lift_definition left :: "  nat" is fst .
lift_definition right :: "  enat" is snd .
lift_definition point :: "nat  " is "λn. (n, enat n)" by simp
lift_definition init :: "nat  " is "λn. (0, enat n)" by auto
abbreviation mem where "mem n I  (left I  n  n  right I)"
lift_definition subtract :: "nat    " is
  "λn (i, j). (i - n, j - enat n)" by (auto simp: diff_enat_def split: enat.splits)
lift_definition add :: "nat    " is
  "λn (a, b). (a, b + enat n)" by (auto simp add: add_increasing2)

lemma left_right: "left I  right I"
  by transfer auto

lemma point_simps[simp]:
  "left (point n) = n"
  "right (point n) = n"
  by (transfer; auto)+

lemma init_simps[simp]:
  "left (init n) = 0"
  "right (init n) = n"
  by (transfer; auto)+

lemma subtract_simps[simp]:
  "left (subtract n I) = left I - n"
  "right (subtract n I) = right I - n"
  "subtract 0 I = I"
  "subtract x (point y) = point (y - x)"
  by (transfer; auto)+

definition shifted :: "   set" where
  "shifted I = (λn. subtract n I) ` {0 .. (case right I of   left I | enat n  n)}"

lemma subtract_too_much: "i > (case right I of   left I | enat n  n) 
  subtract i I = subtract (case right I of   left I | enat n  n) I"
  by transfer (auto split: enat.splits)

lemma subtract_shifted: "subtract n I  shifted I"
  by (cases "n  (case right I of   left I | enat n  n)")
    (auto simp: shifted_def subtract_too_much)

lemma finite_shifted: "finite (shifted I)"
  unfolding shifted_def by auto

definition interval :: "nat  enat  " where
  "interval l r = (if l  r then Abs_ℐ (l, r) else undefined)"

lemma [code abstract]: "Rep_ℐ (interval l r) = (if l  r then (l, r) else Rep_ℐ undefined)"
  unfolding interval_def using Abs_ℐ_inverse by simp

(*<*)
end
(*>*)