# Theory ValueProps

```subsection "Properties about values"

theory ValueProps
imports Values
begin

inductive_cases fun_le_inv[elim]: "t1 ≲ t2" and
vfun_le_inv[elim!]: "VFun t1 ⊑ VFun t2" and
le_fun_nat_inv[elim!]: "VFun t2 ⊑ VNat x1" and
le_fun_cons_inv[elim!]: "(v1, v2) # t1 ≲ t2" and
le_any_nat_inv[elim!]: "v ⊑ VNat n" and
le_nat_any_inv[elim!]: "VNat n ⊑ v" and
le_fun_any_inv[elim!]: "VFun t ⊑ v" and
le_any_fun_inv[elim!]: "v ⊑ VFun t"

lemma fun_le_cons: "(a # t1) ≲ t2 ⟹ t1 ≲ t2"
by (case_tac a) auto

function val_size :: "val ⇒ nat" and fun_size :: "func ⇒ nat" where
"val_size (VNat n) = 0" |
"val_size (VFun t) = 1 + fun_size t" |
"fun_size [] = 0" |
"fun_size ((v1,v2)#t) = 1 + val_size v1 + val_size v2 + fun_size t"
by pat_completeness auto
termination val_size by size_change

lemma val_size_mem: "(a, b) ∈ set t ⟹ val_size a + val_size b < fun_size t"
by (induction t) auto
lemma val_size_mem_l: "(a, b) ∈ set t ⟹ val_size a < fun_size t"
by (induction t) auto
lemma val_size_mem_r: "(a, b) ∈ set t ⟹ val_size b < fun_size t"
by (induction t) auto

lemma val_fun_le_refl: "∀ v t. n = val_size v + fun_size t ⟶ v ⊑ v ∧ t ≲ t"
proof (induction n rule: nat_less_induct)
case (1 n)
show ?case apply clarify apply (rule conjI)
proof -
fix v::val and t::func assume n: "n = val_size v + fun_size t"
show "v ⊑ v"
proof (cases v)
case (VNat x1)
then show ?thesis by auto
next
case (VFun t')
let ?m = "val_size (VNat 0) + fun_size t'"
from 1 n VFun have "t' ≲ t'"
apply (erule_tac x="?m" in allE) apply (erule impE)
apply force apply (erule_tac x="VNat 0" in allE) apply (erule_tac x="t'" in allE)
apply simp done
from this VFun show ?thesis by force
qed
next
fix v::val and t::func assume n: "n = val_size v + fun_size t"
show "t ≲ t"
apply (rule fun_le) apply clarify
proof -
fix v1 v2 assume v12: "(v1,v2) ∈ set t"
from 1 v12 have v11: "v1 ⊑ v1"
apply (erule_tac x="val_size v1 + fun_size []" in allE)
apply (erule impE) using n apply simp apply (frule val_size_mem) apply force
apply (erule_tac x=v1 in allE) apply (erule_tac x="[]" in allE) apply force done
from 1 v12 have v22: "v2 ⊑ v2"
apply (erule_tac x="val_size v2 + fun_size []" in allE)
apply (erule impE) using n apply simp apply (frule val_size_mem) apply force
apply (erule_tac x=v2 in allE) apply (erule_tac x="[]" in allE) apply force done
from v12 v11 v22
show "∃ v3 v4. (v3,v4) ∈ set t ∧ v1 ⊑ v3 ∧ v3 ⊑ v1 ∧ v2 ⊑ v4 ∧ v4 ⊑ v2" by blast
qed
qed
qed

proposition val_le_refl[simp]: fixes v::val shows "v ⊑ v" using val_fun_le_refl by auto

lemma fun_le_refl[simp]: fixes t::func shows "t ≲ t" using val_fun_le_refl by auto

definition val_eq :: "val ⇒ val ⇒ bool" (infix "∼" 52) where
"val_eq v1 v2 ≡ (v1 ⊑ v2 ∧ v2 ⊑ v1)"

definition fun_eq :: "func ⇒ func ⇒ bool" (infix "∼" 52) where
"fun_eq t1 t2 ≡ (t1 ≲ t2 ∧ t2 ≲ t1)"

lemma vfun_eq[intro!]: "t ∼ t' ⟹ VFun t ∼ VFun t'"
apply (simp add: val_eq_def fun_eq_def)
apply (rule conjI) apply (erule conjE) apply (rule vfun_le) apply assumption
apply (erule conjE) apply (rule vfun_le) apply assumption
done

lemma val_eq_refl[simp]: fixes v::val shows "v ∼ v"
by (simp add: val_eq_def)

lemma val_eq_symm: fixes v1::val and v2::val shows "v1 ∼ v2 ⟹ v2 ∼ v1"
unfolding val_eq_def by blast

lemma val_le_fun_le_trans:
"∀ v2 t2. n = val_size v2 + fun_size t2 ⟶
(∀ v1 v3. v1 ⊑ v2 ⟶ v2 ⊑ v3 ⟶ v1 ⊑ v3)
∧ (∀ t1 t3. t1 ≲ t2 ⟶ t2 ≲ t3 ⟶ t1 ≲ t3)"
proof (induction n rule: nat_less_induct)
case (1 n)
show ?case apply clarify
proof
fix v2 t2 assume n: "n = val_size v2 + fun_size t2"
show "∀v1 v3. v1 ⊑ v2 ⟶ v2 ⊑ v3 ⟶ v1 ⊑ v3" apply clarify
proof -
fix v1 v3 assume v12: "v1 ⊑ v2" and v23: "v2 ⊑ v3"
show "v1 ⊑ v3"
proof (cases v2)
case (VNat n)
from VNat v12 have v1: "v1 = VNat n" by auto
from VNat v23 have v3: "v3 = VNat n" by auto
from v1 v3 show ?thesis by auto
next
case (VFun t2')
from v12 VFun obtain t1 where t12: "t1 ≲ t2'" and v1: "v1 = VFun t1" by auto
from v23 VFun obtain t3 where t23: "t2' ≲ t3" and v3: "v3 = VFun t3" by auto
let ?m = "val_size (VNat 0) + fun_size t2'"
from 1 n VFun have IH: "∀t1 t3. t1 ≲ t2' ⟶ t2' ≲ t3 ⟶ t1 ≲ t3"
apply simp apply (erule_tac x="?m" in allE) apply (erule impE) apply force
apply (erule_tac x="VNat 0" in allE)apply (erule_tac x="t2'" in allE)
apply auto done
from t12 t23 IH have "t1 ≲ t3" by auto
from this v1 v3 show ?thesis apply auto done
qed
qed
next
fix v5 t2 assume n: "n = val_size v5 + fun_size t2"
show "∀t1 t3. t1 ≲ t2 ⟶ t2 ≲ t3 ⟶ t1 ≲ t3" apply clarify
proof -
fix t1 t3 v1 v2 assume t12: "t1 ≲ t2" and t23: "t2 ≲ t3" and v12: "(v1,v2) ∈ set t1"
from v12 t12 obtain v1' v2' where v12p: "(v1',v2') ∈ set t2" and
v1_v1p: "v1 ⊑ v1'" and v11p: "v1' ⊑ v1" and v22p: "v2 ⊑ v2'" and v2p_v2: "v2' ⊑ v2" by blast
from v12p t23 obtain v1'' v2'' where v12pp: "(v1'',v2'') ∈ set t3" and
v1p_v1pp: "v1' ⊑ v1''" and v11pp: "v1'' ⊑ v1'" and
v22pp: "v2' ⊑ v2''" and v2pp_v2p: "v2'' ⊑ v2'" by blast

from v12p have sv1p: "val_size v1' < fun_size t2" using val_size_mem_l by blast
from v12 1 v11p v11pp n sv1p have v1pp_v1: "v1'' ⊑ v1"
apply (erule_tac x="val_size v1' + fun_size []" in allE)
apply (erule impE) apply force apply (erule_tac x=v1' in allE)
apply (erule_tac x="[]" in allE) apply (erule impE) apply force
apply (erule conjE) apply blast done

from v12p have sv2p: "val_size v2' < fun_size t2" using val_size_mem_r by blast
from v12 1 v22p v22pp n sv2p have v2_v2pp: "v2 ⊑ v2''"
apply (erule_tac x="val_size v2' + fun_size []" in allE)
apply (erule impE) apply force apply (erule_tac x=v2' in allE)
apply (erule_tac x="[]" in allE) apply (erule impE) apply force
apply (erule conjE) apply blast done

from v12 1 v1_v1p v1p_v1pp n sv1p have v1_v1pp: "v1 ⊑ v1''"
apply (erule_tac x="val_size v1' + fun_size []" in allE)
apply (erule impE) apply force apply (erule_tac x=v1' in allE)
apply (erule_tac x="[]" in allE) apply (erule impE) apply force
apply (erule conjE) apply blast done

from v12 1 v2pp_v2p v2p_v2 n sv2p have v2pp_v2: "v2'' ⊑ v2"
apply (erule_tac x="val_size v2' + fun_size []" in allE)
apply (erule impE) apply force apply (erule_tac x=v2' in allE)
apply (erule_tac x="[]" in allE) apply (erule impE) apply force
apply (erule conjE) apply blast done

from v12pp v1pp_v1 v2_v2pp v1_v1pp v2pp_v2
show " ∃v3 v4. (v3, v4) ∈ set t3 ∧ v1 ⊑ v3 ∧ v3 ⊑ v1 ∧ v2 ⊑ v4 ∧ v4 ⊑ v2" by blast
qed
qed
qed

proposition val_le_trans: fixes v2::val shows "⟦ v1 ⊑ v2; v2 ⊑ v3 ⟧ ⟹ v1 ⊑ v3"
using val_le_fun_le_trans by blast

lemma fun_le_trans: "⟦ t1 ≲ t2; t2 ≲ t3 ⟧ ⟹ t1 ≲ t3"
using val_le_fun_le_trans by blast

lemma val_eq_trans: fixes v1::val and v2::val and v3::val
assumes v12: "v1 ∼ v2" and v23: "v2 ∼ v3" shows "v1 ∼ v3"
using v12 v23 apply (simp only: val_eq_def) using val_le_trans apply blast done

lemma fun_eq_refl[simp]: fixes t::func shows "t ∼ t"
by (simp add: fun_eq_def)

lemma fun_eq_trans: fixes t1::func and t2::func and t3::func
assumes t12: "t1 ∼ t2" and t23: "t2 ∼ t3" shows "t1 ∼ t3"
using t12 t23 unfolding fun_eq_def apply clarify apply (rule conjI)
apply (rule fun_le_trans) apply assumption apply assumption
apply (rule fun_le_trans) apply assumption apply assumption
done

lemma append_fun_le:
"⟦ t1' ≲ t1; t2' ≲ t2 ⟧ ⟹ t1' @ t2' ≲ t1 @ t2"
apply (rule fun_le) apply clarify apply simp apply (erule fun_le_inv)+ apply blast done

lemma append_fun_equiv:
"⟦ t1' ∼ t1; t2' ∼ t2 ⟧ ⟹ t1' @ t2' ∼ t1 @ t2"
apply (simp add: val_eq_def fun_eq_def) using append_fun_le apply blast done

lemma append_leq_symm: "t2 @ t1 ≲ t1 @ t2"
apply (rule fun_le) apply force done

lemma append_eq_symm: "t2 @ t1 ∼ t1 @ t2"
unfolding fun_eq_def val_eq_def apply (rule conjI)
apply (rule append_leq_symm) apply (rule append_leq_symm) done

lemma le_nat_any[simp]: "VNat n ⊑ v ⟹ v = VNat n"
by (cases v) auto

lemma le_any_nat[simp]: "v ⊑ VNat n ⟹ v = VNat n"
by (cases v) auto

lemma le_nat_nat[simp]: "VNat n ⊑ VNat n' ⟹ n = n'"
by auto

end

```