Theory Lexord_List

theory Lexord_List
imports Main
begin

typedef 'a lexlist = "{xs::'a list. True}"
  morphisms unlex Lex
by auto

definition "lexlist  Lex"

lemma lexlist_ext:
  "Lex xs = Lex ys  xs = ys"
by (auto simp: Lex_inject)

lemma Lex_unlex [simp, code abstype]:
  "Lex (unlex lxs) = lxs"
  by (fact unlex_inverse)

lemma unlex_lexlist [simp, code abstract]:
  "unlex (lexlist xs) = xs"
  by (metis lexlist_ext unlex_inverse lexlist_def)

definition list_less :: "'a :: ord list  'a list  bool" where 
  "list_less xs ys  (xs, ys)  lexord {(u, v). u < v}"

definition list_le where
  "list_le xs ys  list_less xs ys  xs = ys"

lemma not_less_Nil [simp]: "¬ list_less x []"
  by (simp add: list_less_def)

lemma Nil_less_Cons [simp]: "list_less [] (a # x)"
  by (simp add: list_less_def)

lemma Cons_less_Cons [simp]: "list_less (a # x) (b # y)  a < b  a = b  list_less x y"
  by (simp add: list_less_def)

lemma le_Nil [simp]: "list_le x []  x = []"
  unfolding list_le_def by (cases x) auto

lemma Nil_le_Cons [simp]: "list_le [] x"
  unfolding list_le_def by (cases x) auto

lemma Cons_le_Cons [simp]: "list_le (a # x) (b # y)  a < b  a = b  list_le x y"
  unfolding list_le_def by auto

lemma less_list_code [code]:
  "list_less xs []  False"
  "list_less [] (x # xs)  True"
  "list_less (x # xs) (y # ys)  x < y  x = y  list_less xs ys"
  by simp_all

lemma less_eq_list_code [code]:
  "list_le (x # xs) []  False"
  "list_le [] xs  True"
  "list_le (x # xs) (y # ys)  x < y  x = y  list_le xs ys"
  by simp_all

instantiation  lexlist :: (ord) ord
begin

definition
  lexlist_less_def: "xs < ys  list_less (unlex xs) (unlex ys)"

definition
  lexlist_le_def: "(xs :: _ lexlist)  ys  list_le (unlex xs) (unlex ys)"

instance ..

lemmas lexlist_ord_defs = lexlist_le_def lexlist_less_def list_le_def list_less_def

end

instance lexlist :: (order) order
proof
  fix xs :: "'a lexlist"
  show "xs  xs" by (simp add: lexlist_le_def list_le_def)
next
  fix xs ys zs :: "'a lexlist"
  assume "xs  ys" and "ys  zs"
  then show "xs  zs"
    apply (auto simp add: lexlist_ord_defs)
    apply (rule lexord_trans)
    apply (auto intro: transI)
    done
next
  fix xs ys :: "'a lexlist"
  assume "xs  ys" and "ys  xs"
  then show "xs = ys"
    apply (auto simp add: lexlist_ord_defs)
    apply (rule lexord_irreflexive [THEN notE])
    defer
    apply (rule lexord_trans)
    apply (auto intro: transI simp: unlex_inject)
    done
next
  fix xs ys :: "'a lexlist"
  show "xs < ys  xs  ys  ¬ ys  xs"
    apply (auto simp add: lexlist_ord_defs)
    defer
    apply (rule lexord_irreflexive [THEN notE])
    apply auto
    apply (rule lexord_irreflexive [THEN notE])
    defer
    apply (rule lexord_trans)
    apply (auto intro: transI)
    done
qed

instance lexlist :: (linorder) linorder
proof
  fix xs ys :: "'a lexlist"
  have "(unlex xs, unlex ys)  lexord {(u, v). u < v}  unlex xs = unlex ys  (unlex ys, unlex xs)  lexord {(u, v). u < v}"
    by (rule lexord_linear) auto
  then show "xs  ys  ys  xs"
    by (auto simp add: lexlist_ord_defs unlex_inject)
qed

end