src/HOL/HOLCF/Library/List_Predomain.thy
author blanchet
Fri, 17 Dec 2010 23:09:53 +0100
changeset 41260 ff38ea43aada
parent 41112 866148b76247
child 41292 2b7bc8d9fd6e
permissions -rw-r--r--
remove option that doesn't work in Mirabelle anyway (Mirabelle uses Sledgehammer_Provers, not Sledgehammer_Run)

(*  Title:      HOLCF/Library/List_Predomain.thy
    Author:     Brian Huffman
*)

header {* Predomain class instance for HOL list type *}

theory List_Predomain
imports List_Cpo
begin

subsection {* Strict list type *}

domain 'a slist = SNil | SCons "'a" "'a slist"

text {*
  Types @{typ "'a list u"}. and @{typ "'a u slist"} are isomorphic.
*}

fixrec encode_list_u where
  "encode_list_u\<cdot>(up\<cdot>[]) = SNil" |
  "encode_list_u\<cdot>(up\<cdot>(x # xs)) = SCons\<cdot>(up\<cdot>x)\<cdot>(encode_list_u\<cdot>(up\<cdot>xs))"

lemma encode_list_u_strict [simp]: "encode_list_u\<cdot>\<bottom> = \<bottom>"
by fixrec_simp

lemma encode_list_u_bottom_iff [simp]:
  "encode_list_u\<cdot>x = \<bottom> \<longleftrightarrow> x = \<bottom>"
apply (induct x, simp_all)
apply (rename_tac xs, induct_tac xs, simp_all)
done

fixrec decode_list_u where
  "decode_list_u\<cdot>SNil = up\<cdot>[]" |
  "ys \<noteq> \<bottom> \<Longrightarrow> decode_list_u\<cdot>(SCons\<cdot>(up\<cdot>x)\<cdot>ys) =
    (case decode_list_u\<cdot>ys of up\<cdot>xs \<Rightarrow> up\<cdot>(x # xs))"

lemma decode_list_u_strict [simp]: "decode_list_u\<cdot>\<bottom> = \<bottom>"
by fixrec_simp

lemma decode_encode_list_u [simp]: "decode_list_u\<cdot>(encode_list_u\<cdot>x) = x"
by (induct x, simp, rename_tac xs, induct_tac xs, simp_all)

lemma encode_decode_list_u [simp]: "encode_list_u\<cdot>(decode_list_u\<cdot>y) = y"
apply (induct y, simp, simp)
apply (case_tac a, simp)
apply (case_tac "decode_list_u\<cdot>y", simp, simp)
done

subsection {* Lists are a predomain *}

instantiation list :: (predomain) predomain
begin

definition
  "liftemb = emb oo encode_list_u"

definition
  "liftprj = decode_list_u oo prj"

definition
  "liftdefl (t::('a list) itself) = DEFL(('a\<^sub>\<bottom>) slist)"

instance proof
  have "ep_pair encode_list_u decode_list_u"
    by (rule ep_pair.intro, simp_all)
  thus "ep_pair liftemb (liftprj :: udom \<rightarrow> ('a list) u)"
    unfolding liftemb_list_def liftprj_list_def
    using ep_pair_emb_prj by (rule ep_pair_comp)
  show "cast\<cdot>LIFTDEFL('a list) = liftemb oo (liftprj :: udom \<rightarrow> ('a list) u)"
    unfolding liftemb_list_def liftprj_list_def liftdefl_list_def
    by (simp add: cfcomp1 cast_DEFL)
qed

end

lemma liftdefl_list [domain_defl_simps]:
  "LIFTDEFL('a::predomain list) = slist_defl\<cdot>LIFTDEFL('a)"
unfolding liftdefl_list_def by (simp add: domain_defl_simps)

subsection {* Continuous map operation for lists *}

definition
  list_map :: "('a::predomain \<rightarrow> 'b::predomain) \<rightarrow> 'a list \<rightarrow> 'b list"
where
  "list_map = (\<Lambda> f xs. map (\<lambda>x. f\<cdot>x) xs)"

lemma list_map_simps [simp]:
  "list_map\<cdot>f\<cdot>[] = []"
  "list_map\<cdot>f\<cdot>(x # xs) = f\<cdot>x # list_map\<cdot>f\<cdot>xs"
unfolding list_map_def by simp_all

lemma list_map_ID [domain_map_ID]: "list_map\<cdot>ID = ID"
unfolding list_map_def ID_def
by (simp add: Abs_cfun_inverse cfun_def)

lemma deflation_list_map [domain_deflation]:
  "deflation d \<Longrightarrow> deflation (list_map\<cdot>d)"
apply default
apply (induct_tac x, simp_all add: deflation.idem)
apply (induct_tac x, simp_all add: deflation.below)
done

subsection {* Configuring list type to work with domain package *}

lemma encode_list_u_map:
  "encode_list_u\<cdot>(u_map\<cdot>(list_map\<cdot>f)\<cdot>(decode_list_u\<cdot>xs))
    = slist_map\<cdot>(u_map\<cdot>f)\<cdot>xs"
apply (induct xs)
apply (simp, subst slist_map_unfold, simp)
apply (simp, subst slist_map_unfold, simp add: SNil_def)
apply (case_tac a, simp, rename_tac b)
apply (case_tac "decode_list_u\<cdot>xs")
apply (drule_tac f="encode_list_u" in cfun_arg_cong, simp)
by (simp, subst slist_map_unfold, simp add: SCons_def)

lemma isodefl_list_u [domain_isodefl]:
  fixes d :: "'a::predomain \<rightarrow> 'a"
  assumes "isodefl (u_map\<cdot>d) t"
  shows "isodefl (u_map\<cdot>(list_map\<cdot>d)) (slist_defl\<cdot>t)"
using assms [THEN isodefl_slist] unfolding isodefl_def
unfolding emb_u_def prj_u_def liftemb_list_def liftprj_list_def
by (simp add: cfcomp1 encode_list_u_map)

setup {*
  Domain_Take_Proofs.add_rec_type (@{type_name "list"}, [true])
*}

end