Theory Finitary

theory Finitary
imports Ordinal
begin

class finitary =
  fixes hf_of :: "'a ⇒ hf"
  assumes inj: "inj hf_of"
begin
  lemma hf_of_eq_iff [simp]: "hf_of x = hf_of y ⟷ x=y"
    using inj by (auto simp: inj_on_def)
end

instantiation unit :: finitary
begin
  definition hf_of_unit_def: "hf_of (u::unit) ≡ 0"
  instance
    by intro_classes (auto simp: inj_on_def hf_of_unit_def)
end

instantiation bool :: finitary
begin
  definition hf_of_bool_def: "hf_of b ≡ if b then 1 else 0"
  instance 
    by intro_classes (auto simp: inj_on_def hf_of_bool_def)
end

instantiation nat :: finitary
begin
  definition hf_of_nat_def: "hf_of ≡ ord_of"
  instance 
    by intro_classes (auto simp: inj_on_def hf_of_nat_def)
end

instantiation int :: finitary
begin
  definition hf_of_int_def: 
    "hf_of i ≡ if i≥(0::int) then ⟨0, hf_of (nat i)⟩ else ⟨1, hf_of (nat (-i))⟩"
  instance 
    by intro_classes (auto simp: inj_on_def hf_of_int_def)
end

text ‹Strings are char lists, and are not considered separately.›
instantiation char :: finitary
begin
  definition hf_of_char_def: 
    "hf_of x ≡ hf_of (of_char x :: nat)"
  instance 
    by standard (auto simp: inj_on_def hf_of_char_def)
end

instantiation prod :: (finitary,finitary) finitary
begin
  definition hf_of_prod_def: 
    "hf_of ≡ λ(x,y). ⟨hf_of x, hf_of y⟩"
  instance 
    by intro_classes (auto simp: inj_on_def hf_of_prod_def)
end

instantiation sum :: (finitary,finitary) finitary
begin
  definition hf_of_sum_def: 
    "hf_of ≡ case_sum (HF.Inl o hf_of) (HF.Inr o hf_of)"
  instance 
    by intro_classes (auto simp: inj_on_def hf_of_sum_def split: sum.split_asm)
end

instantiation option :: (finitary) finitary
begin
  definition hf_of_option_def: 
    "hf_of ≡ case_option 0 (λx. ⦃hf_of x⦄)"
  instance 
    by intro_classes (auto simp: inj_on_def hf_of_option_def split: option.split_asm)
end

instantiation list :: (finitary) finitary
begin
  primrec hf_of_list where
    "hf_of_list Nil = 0"
  | "hf_of_list (x#xs) = ⟨hf_of x, hf_of_list xs⟩"
  
lemma [simp]: fixes x :: "'a list" shows "hf_of x = hf_of y ⟹ x = y"
  proof (induction x arbitrary: y)
    case Nil
    then show ?case by (cases y) auto
  next
    case (Cons a x)
    then show ?case by (cases y) auto
  qed

instance 
  by intro_classes (auto simp: inj_on_def)
end

end