Theory Basic_Terms

theory Basic_Terms 
  imports Sorted_Contexts
begin

lemma map_le_map_add_left:
  assumes disj: "dom m  dom n = {}"
  shows "m m m ++ n"
  using map_le_map_add map_add_comm[OF disj] by auto

section ‹Basic Terms›

text ‹Given two signatures C and D, a term f(s1,…,sn)› is called a basic term
if f : [σ1,…,σn] → τ in D› and s1 : σ1,…,sn : σn in 𝒯(C,X)›.
We define the sorted set of basic terms as follows.›

fun Basic_Term :: "('f,'s) ssig  ('f,'s) ssig  ('v  's)  ('f,'v) term  's" ("𝒯B'(_,_,_')")
  where "𝒯B(C,D,X) (Var x) = None"
  | "𝒯B(C,D,X) (Fun f ss) = (case those (map 𝒯(C,X) ss) of Some σs  D (f,σs) | _  None)"

abbreviation ground_Basic_Term ("𝒯B'(_,_')") where
  "𝒯B(C,D)  𝒯B(C,D,λx. None) :: ('f,unit) term  's"

lemma Var_hastype_Basic:
  "Var x : σ in 𝒯B(C,D,X)  False" by (simp add: hastype_def)

lemma Fun_hastype_Basic:
  "Fun f ss : τ in 𝒯B(C,D,X)  (σs. f : σs  τ in D  ss :l σs in 𝒯(C,X))"
  apply (unfold hastype_list_iff_those)
  by (auto simp: hastype_def fun_hastype_def split:option.split_asm)

lemma hastype_Basic:
  "s : τ in 𝒯B(C,D,X)  (f ss σs. s = Fun f ss  f : σs  τ in D  ss :l σs in 𝒯(C,X))"
  by (cases s, auto simp: Var_hastype_Basic Fun_hastype_Basic)

lemma in_dom_Basic:
  "s  dom 𝒯B(C,D,X)  (f ss σs τ. s = Fun f ss  f : σs  τ in D  ss :l σs in 𝒯(C,X))"
  by (auto simp: in_dom_iff_ex_type hastype_Basic)

lemma hastype_BasicE:
  assumes "s : τ in 𝒯B(C,D,X)"
    and "f ss σs. s = Fun f ss  f : σs  τ in D  ss :l σs in 𝒯(C,X)  thesis"
  shows thesis
  using assms by (auto simp: hastype_Basic)

lemma hastype_BasicI:
  "s = Fun f ss  f : σs  τ in D  ss :l σs in 𝒯(C,X)  s : τ in 𝒯B(C,D,X)"
  by (auto simp: hastype_Basic)

lemma Basic_mono:
  assumes D: "D m D'" and C: "C m C'" and X: "X m X'"
  shows "𝒯B(C,D,X) m 𝒯B(C',D',X')"
proof (safe intro!: subssetI elim!: hastype_BasicE)
  fix f ss σs τ assume f: "f : σs  τ in D" and ss: "ss :l σs in 𝒯(C,X)"
  from subssigD[OF D f] Term_mono[OF C X, THEN subsset_hastype_listD, OF ss]
  show "Fun f ss : τ in 𝒯B(C',D',X')"
    by (intro hastype_BasicI[OF refl])
qed

text ‹Basic terms are terms of the joint signature, if the signatures are disjoint.›

lemma Basic_Term:
  assumes disj: "dom C  dom D = {}"
  shows "𝒯B(C,D,X) m 𝒯(C++D,X)"
proof (intro subssetI)
  fix s σ
  assume s: "s : σ in 𝒯B(C,D,X)"
  show "s : σ in 𝒯(C++D,X)"
  proof (cases s)
    case (Var x1)
    with s show ?thesis by (auto simp: Var_hastype_Basic)
  next
    case sfss: (Fun f ss)
    with s obtain τs where ss: "ss :l τs in 𝒯(C,X)" and f: "f : τs  σ in D"
      by (auto simp: Fun_hastype_Basic)
    from disj have C: "C m C++D" by (simp add: map_le_map_add_left)
    from Term_mono_left[OF C, THEN subssetD] ss
    have ssF: "ss :l τs in 𝒯(C++D,X)" by (metis subsset_hastype_listD subssetI)
    have "D m C++D" by auto
    from subssigD[OF this f] have fF: "f : τs  σ in C++D".
    with ssF have "Fun f ss : σ in 𝒯(C++D,X)" by (auto simp: Fun_hastype)
    then show ?thesis by (auto simp: sfss)
  qed
qed

text ‹Basic terms are preserved under constructor substitution.›

lemma subst_Basic_Term:
  assumes θ: "θ :s X  𝒯(C,V)" and s: "s : τ in 𝒯B(C,D,X)"
  shows "sθ : τ in 𝒯B(C,D,V)"
proof-
  from s[unfolded hastype_Basic]
  obtain f ss σs where s: "s = Fun f ss" and f: "f : σs  τ in D" and ss: "ss :l σs in 𝒯(C,X)"
    by (auto simp: hastype_Basic)
  from map_subst_hastype[OF θ ss] f
  show ?thesis by (auto simp: hastype_Basic s)
qed

lemma in_dom_Basic_Term_imp_vars: "s  dom 𝒯B(C,D,V)  x  vars s  x  dom V"
  apply (elim in_dom_hastypeE)
  apply (cases s)
  by (auto simp: Fun_hastype_Basic list_all2_conv_all_nth in_set_conv_nth dest!: hastype_in_Term_imp_vars)

lemma in_dom_Basic_empty_subst_id:
  assumes "s  dom 𝒯B(C,D,)"
  shows "sθ = s"
  using assms
  by (auto elim!: in_dom_hastypeE hastype_BasicE simp: o_def map_subst_Term_empty_id)

lemma in_dom_Basic_empty_subst_subst:
  assumes "s  dom 𝒯B(C,D,)"
  shows "sθτ = sundefined"
  using assms
  by (auto elim!: in_dom_hastypeE hastype_BasicE simp: o_def map_subst_subst_Term_empty)

end